CGContextShowText is rendering upside down text (mirror image) - ios

Without my doing anything to request upside down text, CGContextShowText is drawing it in that fashion. It is a mirror image vertically of what it should be.
float font_size = 19.;
CGContextSelectFont (context, "Helvetica", font_size, kCGEncodingMacRoman);
CGContextSetTextDrawingMode (context, kCGTextFill);
CGContextSetRGBStrokeColor (context, 255, 0, 0, 0);
CGContextSetRGBFillColor (context, 255, 0, 0, 0);
CGContextSetTextPosition (context, x, y);
CGContextShowText (context, cstring, strlen(cstring));
How can I fix this? Also why is this the default drawing mode?
Thanks.

This "upsidedownness" commonly comes into play when the API renders to your cgContext from top to bottom, but somehow you're drawing from bottom to top. Anyway, the 2 line solution I use is:
CGAffineTransform trans = CGAffineTransformMakeScale(1, -1);
CGContextSetTextMatrix(tex->cgContext, trans);

Swift 3
let context = UIGraphicsGetCurrentContext()!
let textTransform = CGAffineTransform(scaleX: 1.0, y: -1.0)
context.textMatrix = textTransform

The best solution to this problem is to simply call this at the beginning of your draw routine. (Make sure to only call it once.)
CGAffineTransform transform;
transform = CGAffineTransformConcat(CGContextGetTextMatrix(ctx),
CGAffineTransformMake(1.0, 0.0, 0.0,
-1.0, 0.0, 0.0));
CGContextSetTextMatrix(ctx, transform);

Related

WebGL Perspective Projection

I have a scene of a cube with vertices defined like so
const positions = [
-10.0, 10.0,
10.0, 10.0,
-10.0, -10.0,
10.0, -10.0
];
I'm trying to go from a field of view perspective matrix (not shown) to a specified rectangle perspective projection matrix defined like so
const n = 0.1;
const f = 100.0;
const l = -50;
const r = 50;
const t = 50;
const b = -50;
Float32Array([
(2*n/r-l), 0.0, 0.0, 0.0,
0.0, (2*n/t-b), 0.0, 0.0,
(r+l/r-l), (t+b/t-b), -(f+n/f-n), -1.0,
0.0, 0.0, -(2*f*n/f-n), 0.0
]);
I also have a model matrix that moves the box -6 units in the z index so that it's within the bounds of the near and far clip planes.
Am I right to assume that before transforming anything the coordinates I use to specify the box and perspective matrix are in the same space/frame of reference? Therefore the box should be dead center of the view?
The box renders with the field of view matrix, but not the matrix defined above.
The formulas are not exact. Try this (I have added parentheses only):
Float32Array([
(2*n)/(r-l), 0.0, 0.0, 0.0,
0.0, (2*n)/(t-b), 0.0, 0.0,
(r+l)/(r-l), (t+b)/(t-b), -(f+n)/(f-n), -1.0,
0.0, 0.0, -(2*f*n)/(f-n), 0.0
]);

Metal Tessellation on subdivided quad

I am totally new to tessellation and relatively new to Metal API, and have been referring to this sample code https://developer.apple.com/library/archive/samplecode/MetalBasicTessellation/Introduction/Intro.html
I realise the max tessellation factor on iOS is 16, which is very low for my use case compared to 64 on OSX.
I suppose i'll need to apply tessellation on a quad that has been sub-divided to 4 by 4 smaller sections to begin with, so that after tessellation it will end up into something like one with a tessellation factor of 64?
So, i've changed the input control points to something like this
static const float controlPointPositionsQuad[] = {
-0.8, 0.8, 0.0, 1.0, // upper-left
0.0, 0.8, 0.0, 1.0, // upper-mid
0.0, 0.0, 0.0, 1.0, // mid-mid
-0.8, 0.0, 0.0, 1.0, // mid-left
-0.8, 0.0, 0.0, 1.0, // mid-left
0.0, 0.0, 0.0, 1.0, // mid-mid
0.0, -0.8, 0.0, 1.0, // lower-mid
-0.8, -0.8, 0.0, 1.0, // lower-left
0.0, 0.8, 0.0, 1.0, // upper-mid
0.8, 0.8, 0.0, 1.0, // upper-right
0.8, 0.0, 0.0, 1.0, // mid-right
0.0, 0.0, 0.0, 1.0, // mid-mid
0.0, 0.0, 0.0, 1.0, // mid-mid
0.8, 0.0, 0.0, 1.0, // mid-right
0.8, -0.8, 0.0, 1.0, // lower-right
0.0, -0.8, 0.0, 1.0, // lower-mid
};
and for the drawPatches i changed it to 16 instead of 4.
But the result is that it is only showing only the first 4 points (top left).
if i change the vertex layout stride to this:
vertexDescriptor.layouts[0].stride = 16*sizeof(float);
it is still showing the same.
I don't really know what i'm doing but what i'm going for is similar to tessellating a 3d mesh, but for my case is just a quad with subdivisions.
I am unable to find any tutorial / code samples that teach about this using Metal API.
Can someone please point me to the right direction? thanks!
Here are a few things to check:
Ensure that your tessellation factor compute kernel is generating inside/edge factors for all patches by dispatching a compute grid of the appropriate size.
When dispatching threadgroups to execute your tessellation factor kernel, use 1D threadgroup counts and sizes (such that the total thread count is the number of patches, and the heights of both sizes passed to the dispatch method are 1).
When drawing patches, the first parameter (numberOfPatchControlPoints) should equal the number of control points in each patch (3 for triangles; 4 for quads), and the third parameter should be the number of patches to draw.

Trying to flip an OpenGL texture

I'm trying to invert the Y values of a texture on OpenGL ES 2.0, and have had no luck after several days of experimentation. Here's the code in my didRender block (it's a scene kit scene).
let textureCoordinates: [GLfloat] = [
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0]
let flipVertical: [GLfloat] = [
0.0, 1.0,
1.0, 1.0,
0.0, 0.0,
1.0, 0.0]
glEnableVertexAttribArray(0)
glEnableVertexAttribArray(1)
glVertexAttribPointer(0, 2, GLenum(GL_FLOAT), 0, 0, flipVertical)
glVertexAttribPointer(1, 2, GLenum(GL_FLOAT), 0, 0, textureCoordinates)
glDrawArrays(GLenum(GL_TRIANGLE_STRIP), 0, 4)
glBindTexture(GLenum(GL_TEXTURE_2D), 0)
glFlush()
Is there anything that sticks out to you as wrong? My understanding is that I can flip the texture without having to rewrite to a new texture. Is that true? Thanks!
You don't need a separate vertex attribute to do the flip; just replace the textureCoordinate array with the values from flipVertical (and then delete all of the code related to flipVertical - you don't need it).

How to use CoreText in MonoTouch to write rotated text?

I need to write some text rotated by 90 degrees. I first tried with a UILabel rotated with CGAffineTransform:
this.myLabel.Center = this.myLabel.Frame.Location;
this.myLabel.Transform = CGAffineTransform.MakeRotation (-(float)Math.PI / 2.0f);
It rotated it just right, but fonts now look all blurred and difficult to read.
Is there a way to use the CoreText library to make a simple text rotation in a UILabel that doesn't look blurred?
Thank you in advance!
In case you missed it Xamarin provides a sample on github that use CoreText to draw (non-rotated) text.
Since the text ends up as a path it should not be hard to rotate the whole text. OTOH CoreText is more much complicated than the older API - that's the price to pay to get (way) more control.
You could use Core Graphics. It's a little involved, but will do the trick.
A sample would be:
void MyDrawText (CGContextRef myContext, CGRect contextRect) // 1
{
float w, h;
w = contextRect.size.width;
h = contextRect.size.height;
CGAffineTransform myTextTransform; // 2
CGContextSelectFont (myContext, // 3
"Helvetica-Bold",
h/10,
kCGEncodingMacRoman);
CGContextSetCharacterSpacing (myContext, 10); // 4
CGContextSetTextDrawingMode (myContext, kCGTextFillStroke); // 5
CGContextSetRGBFillColor (myContext, 0, 1, 0, .5); // 6
CGContextSetRGBStrokeColor (myContext, 0, 0, 1, 1); // 7
myTextTransform = CGAffineTransformMakeRotation (myRadianRotation); // 8
CGContextSetTextMatrix (myContext, myTextTransform); // 9
CGContextShowTextAtPoint (myContext, 40, 0, "Quartz 2D", 9); // 10
}

Using Multiple CGAffineTransforms On Text Matrix

I am displaying text using Quartz. Here is my code:
CGContextRef myContext = UIGraphicsGetCurrentContext();
CGContextSelectFont(myContext, "Helvetica", 12, kCGEncodingMacRoman);
CGContextSetCharacterSpacing(myContext, 8);
CGContextSetTextDrawingMode(myContext, kCGTextFillStroke);
CGContextSetRGBFillColor(myContext, 0, 0, 0, 1);
CGContextSetRGBStrokeColor(myContext, 0, 0, 0, 1);
CGContextSetTextMatrix(myContext,CGAffineTransformMake(1, 0, 0, -1, 0, 0));
CGContextShowTextAtPoint(myContext, textOrigin.x, textOrigin.y,[way.name UTF8String],[way.name length]);
This displays my text the right way up and in the right direction, however I also need to add a rotation to the text using CGAffineTransformMakeRotation(angle);. I can't seem to work out how to aply two affine transforms to the text matrix, though, without one overwriting the other. Any help would be great.
You can combine matrices with CGAffineTransformConcat, e.g.
CGAffineTransform finalTransf = CGAffineTransformConcat(t1, t2);
If you just need to apply rotation to an existing matrix, use CGAffineTransformRotate, e.g.
CGAffineTransform t = CGAffineTransformMake(1, 0, 0, -1, 0, 0);
CGAffineTransform t = CGAffineTransformRotate(t, M_PI/2);
CGContextSetTextMatrix(myContext, t);
To supplement #kennytm's answer, to apply more than two transforms you can do the following:
var t = CGAffineTransformIdentity
t = CGAffineTransformTranslate(t, CGFloat(100), CGFloat(300))
t = CGAffineTransformRotate(t, CGFloat(M_PI_4))
t = CGAffineTransformScale(t, CGFloat(-1), CGFloat(2))
// ... add as many as you want, then apply it to to the view
imageView.transform = t
Go here to see my full answer.

Resources