I am writing an extension / widgets for gnome-shell.So I want to show some information using text. Actually I want to put text in middle of the circle using pangoCairo but I can't figure out how can I put text using pangoCairo?
here is my code of drawing circles with a function to set text middle of the circles but the text is not showing in the middle.
draw_stuff(canvas, cr, width, height) {
cr.setSourceRGBA(1,1,1,0.2);
cr.save ();
cr.setOperator (Cairo.Operator.CLEAR);
cr.paint ();
cr.restore ();
cr.setOperator (Cairo.Operator.OVER);
cr.scale (width, height);
cr.setLineCap (Cairo.LineCap.BUTT);
//test
cr.setLineWidth (0.08);
cr.translate (0.5, 0.5);
cr.arc (0, 0, 0.4, 0, Math.PI * 2);
cr.stroke ();
cr.setSourceRGBA(1,1,1,0.8);
cr.rotate(-Math.PI/2);
cr.save();
cr.arc (0,0, 0.4, 0, this.currentR /100 * 2 * Math.PI);
cr.stroke();
cr.setSourceRGBA(1,1,1,0.9);
cr.save();
cr.arc (0,0, 0.25, 0, 2 * Math.PI);
cr.fill();
cr.moveTo(0, 0);
cr.setSourceRGBA(0,0,0,0.9);
cr.save();
this.text_show(cr, "WoW");
cr.restore();
return true; }
update() { this.currentR = 60;
this._canvas.connect ("draw", this.draw_stuff.bind(this));
this._canvas.invalidate();}
text_show(cr, showtext, font = "DejaVuSerif Bold 16") {
let pl = PangoCairo.create_layout(cr);
pl.set_text(showtext, -1);
pl.set_font_description(Pango.FontDescription.from_string(font));
PangoCairo.update_layout(cr, pl);
let [w, h] = pl.get_pixel_size();
cr.relMoveTo(-w / 2, 0);
PangoCairo.show_layout(cr, pl);
cr.relMoveTo(w / 2, 0);}
I dont know what's wrong here?
let [w, h] = pl.get_pixel_size();
cr.relMoveTo(-w / 2, 0);
You are placing your text something like 1000 pixels off the screen. get_pixel_size() is documented as:
pango_layout_get_size() returns the width and height scaled by PANGO_SCALE.
and PANGO_SCALE has the value 1024:
Thus, you need to change the code above to
let [w, h] = pl.get_pixel_size();
cr.relMoveTo(-w / 2048, 0);
Bonus points for not hardcoding the value of PANGO_SCALE and instead getting it from your Pango API bindings. However, for that I don't know enough about gnome-shell-extensions. Is this code in Javascript? Dunno.
Related
I am starting out with pymunk and have a static floor with a dynamic object (ball). When the ball falls onto the floor there is an initial overlap where the ball is absorbed into the floor before slowly being pushed back up.
Why does this happen? Is this normal?
import pygame
import pymunk
import pymunk.pygame_util
pygame.init()
#game window
SCREEN_WIDTH, SCREEN_HEIGHT = 600, 600
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
#pymunk space
space = pymunk.Space()
space.gravity = (0, 981)
clock = pygame.time.Clock()
fps = 60
dt = 1/60
draw_options = pymunk.pygame_util.DrawOptions(screen)
def create_floor(space, width, height, pos):
body = pymunk.Body(body_type = pymunk.Body.STATIC)
body.position = pos
shape = pymunk.Poly.create_box(body, (width, height))
space.add(body, shape)
def create_ball(space, radius, mass):
body = pymunk.Body()
body.position = (300, 250)
shape = pymunk.Circle(body, radius)
shape.mass = mass
shape.color = (255, 0, 0, 100)
space.add(body, shape)
return shape
ball = create_ball(space, 30, 10)
create_floor(space, SCREEN_WIDTH, 20, (SCREEN_WIDTH / 2, SCREEN_HEIGHT - 10))
run = True
while run:
clock.tick(fps)
space.step(dt)
screen.fill((255, 255, 255))
space.debug_draw(draw_options)
#event handler
for event in pygame.event.get():
if event.type == pygame.QUIT:
run = False
pygame.display.update()
pygame.quit()
Yes, this is normal. There are however things that can be done to minimize this behavior:
The easiest method is to call space.step() with a smaller timestep (and instead call it more times). Replace space.step(dt) with something like this:
for _ in range(10):
space.step(dt/10)
Its also possible to limit the maximum speed that objects move with. The slower they move, the less overlap there will be. Finally, you can also try to adjust the collision_bias parameter on the space.
I am trying to draw ellipse on a rotated PDF but the border of the ellipse appears thick and thin in center
Sample Code:
PdfAnnotation annotation = PdfAnnotation.createSquareCircle(stamper.getWriter(), rect, null, false);
annotation.setFlags(PdfAnnotation.FLAGS_PRINT);
annotation.setColor(getColor(annot.getBorderColor()));
// annotation.setBorder(new PdfBorderArray(2, 2, 2));
// annotation.setColor(getColor(annot.getBorderColor()));
annotation.setBorderStyle(new PdfBorderDictionary(3.5f, PdfBorderDictionary.STYLE_SOLID));
PdfContentByte cb = stamper.getOverContent(page);
if ((int) (orientation % 360) == 90 || (int) (orientation % 360) == 270)
{
w = rect.getHeight();
h = rect.getWidth();
}
else
{
w = rect.getWidth();
h = rect.getHeight();
}
PdfAppearance app = cb.createAppearance(w + 3.5f, h + 3.5f);
app.setColorStroke(getColor(annot.getBorderColor()));
app.setLineWidth(3.5);
app.ellipse(rect.getLeft() + 1.5, rect.getBottom() + 1.5, rect.getRight() - 1.5, rect.getTop() - 1.5);
app.stroke();
annotation.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, app);
stamper.addAnnotation(annotation, page);
As already assumed in a comment a feature of iText (for rotated pages it attempts to pretend to the user that he has an upright coordinate system, not a rotated one) gets into your way. This feature unfortunately does only affect the dimensions of the annotation itself, not of the appearances you create for it.
If a page has a 90° or 270° rotation, therefore, you have to use appearance dimensions whose width and height are switched compared to the annotation dimensions you used.
Furthermore, one also has to consider the switched dimensions when drawing the ellipse on the appearance template. The code in the question and in the example code shared via google drive forgot this.
Finally, one shall not override the switched dimensions of the appearance template using PdfAppearance.setBoundingBox. The code in the example code shared via google drive did this.
False Example
If I create an ellipse annotation with appearance on a rotated page like this:
Rectangle rect = new Rectangle(202 + 6f, 300, 200 + 100, 300 + 150);
PdfAnnotation annotation = PdfAnnotation.createSquareCircle(stamper.getWriter(), rect, null, false);
annotation.setFlags(PdfAnnotation.FLAGS_PRINT);
annotation.setColor(BaseColor.RED);
annotation.setBorderStyle(new PdfBorderDictionary(3.5f, PdfBorderDictionary.STYLE_SOLID));
PdfContentByte cb = stamper.getOverContent(1);
PdfAppearance app = cb.createAppearance(rect.getWidth(), rect.getHeight());
app.setColorStroke(BaseColor.RED);
app.setLineWidth(3.5);
app.ellipse( 1.5, 1.5, rect.getWidth() - 1.5, rect.getHeight() - 1.5);
app.stroke();
annotation.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, app);
stamper.addAnnotation(annotation, 1);
(CreateEllipse test testCreateEllipseAppearanceOnRotated)
I indeed get a funny ellipse:
Correct Example
If I create an ellipse annotation with appearance on a rotated page with switched dimensions like this, though:
Rectangle rect = new Rectangle(202 + 6f, 300, 200 + 100, 300 + 150);
PdfAnnotation annotation = PdfAnnotation.createSquareCircle(stamper.getWriter(), rect, null, false);
annotation.setFlags(PdfAnnotation.FLAGS_PRINT);
annotation.setColor(BaseColor.RED);
annotation.setBorderStyle(new PdfBorderDictionary(3.5f, PdfBorderDictionary.STYLE_SOLID));
PdfContentByte cb = stamper.getOverContent(1);
// switched appearance dimensions
PdfAppearance app = cb.createAppearance(rect.getHeight(), rect.getWidth());
app.setColorStroke(BaseColor.RED);
app.setLineWidth(3.5);
// draw ellipse using switched appearance dimensions
app.ellipse( 1.5, 1.5, rect.getHeight() - 1.5, rect.getWidth() - 1.5);
app.stroke();
annotation.setAppearance(PdfAnnotation.APPEARANCE_NORMAL, app);
stamper.addAnnotation(annotation, 1);
(CreateEllipse test testCreateCorrectEllipseAppearanceOnRotated)
I get the expected ellipse:
I am using libyuv to convert NV21 image format to I420:
void convert(uint8* input, int width, int height) {
int size = width * height * 3/2;
uint8* output = new uint8[size];
uint8* src_y = input;
int src_stride_y = width;
uint8* src_vu = input + (width * height);
int src_stride_vu = width / 2;
uint8* dst_y = output;
int dst_stride_y = width;
uint8* dst_u = dst_y + (width * height);
int dst_stride_u = width / 2;
uint8* dst_v = dst_u + (width * height) / 4;
int dst_stride_v = width / 2;
libyuv::NV21ToI420(src_y, src_stride_y,
src_vu, src_stride_vu,
dst_y, dst_stride_y,
dst_u, dst_stride_u,
dst_v, dst_stride_v,
width, height);
dumpToFile(dst_y, size);
...
}
The size of my input is 640x480.
I display the dumped file using ImageMagick's display:
$ display -size 640x480 -depth 8 -sampling-factor 4:2:0 -colorspace srgb MyI420_1.yuv
However, the colors are messed up in the displayed image. The other aspects of the image look okay.
I am wondering if I am making a mistake in my code. Perhaps my stride calculations are not correct.
Note that if I use my custom function to rearrange V1U1V2U2... as U1U2...V1V2... and dump the output, it displays fine. However, I prefer to use libyuv as it has some optimization for neon, SSE2, etc. Regards.
Your src_stride_vu need to be same as width since it's combined stride to UV pixels interlaced.
I've written a small 2D engine in opengl in the process of making a game. I'm using OpenGL ES 2 and the code compiles and runs on iOS and Mac OSX.
Now I'm extending it to support 3D and I'm having a problem setting up the camera.
I've checked the code a hundred times and I can't finde where the problem is, so maybe someone with experience on this can give an idea.
This is the code I have: I'm posting the part of the code where I think the problem might be, but if something else is needed just ask me.
Matrix4 _getFrustumMatrix(float left, float right, float bottom, float top, float near, float far){
Matrix4 res = Matrix4(2.0 * near / (right - left), 0, 0, 0,
0, 2.0 * near / (top - bottom), 0, 0,
(right + left) / (right - left), (top + bottom) / (top - bottom), -(far + near) / (far - near), -1.0,
0,0, -2.0 * far * near / (far - near), 0);
return res;
}
Matrix4 _getPerspectiveMatrix(float near, float far, float angleOfView){
static float aspectRatio = float(SCREENW)/float(SCREENH);
float top = near * tan(angleOfView * 3.1415927 / 360.0);
float bottom = -top;
float left = bottom * aspectRatio;
float right = top * aspectRatio;
return _getFrustumMatrix(left, right, bottom, top, near, far);
}
Matrix4 _getLookAtMatrix(Vector3 eye, Vector3 at, Vector3 up){
Vector3 forward, side;
forward = at - eye;
forward.normalize();
side = forward ^ up;
side.normalize();
up = side ^ forward;
Matrix4 res = Matrix4(side.x, up.x, -forward.x, 0,
side.y, up.y, -forward.y, 0,
side.z, up.z, -forward.z, 0,
0, 0, 0, 1);
res.translate(Vector3(0 - eye));
return res;
}
void Scene3D::_deepRender(){
cameraEye = Vector3(10,0,40);
cameraAt = Vector3(0,0,0);
cameraUp = Vector3(0,1,0);
MatrixStack::push();
Matrix4 projection = _getPerspectiveMatrix(1, 100, 45);
Matrix4 view = _getLookAtMatrix(cameraEye, cameraAt, cameraUp);
MatrixStack::set(projection * view);
Space3D::_deepRender();
MatrixStack::pop();
}
The drawn object is a representation of the axes where x=red, y=green, z=blue, and it's located at (0,0,0).
If I put the eye at (0,0,40) everything looks as expected:
If I put the eye at (10,0,40) then the object is not drawn in the middle of the screen as it should be.
This is the Matrix4::translate method:
void Matrix4::translate(const Vector3& v) {
a14 += a11 * v.x + a12 * v.y + a13 * v.z;
a24 += a21 * v.x + a22 * v.y + a23 * v.z;
a34 += a31 * v.x + a32 * v.y + a33 * v.z;
a44 += a41 * v.x + a42 * v.y + a43 * v.z;
}
EDIT: To add some information:
Using _getLookAtMatrix() with this parameters:
cameraEye = Vector3(40,40,40);
cameraAt = Vector3(0,0,0);
cameraUp = Vector3(0,1,0);
Should give me an equivalent matrix to this one?
Matrix4 view;
view.setIdentity();
view.translate(Vector3(0,0,-69.2820323)); // 69.2820323 is the length of Vector3(40,40,40)
view.rotate(45, Vector3(1,0,0));
view.rotate(-45, Vector3(0,1,0));
At least those transformations makes sense to me and the resulting image looks as what I should expect.
But this matrix compared to the one I get using _getLookAtMatrix() are very different:
view:
0.707106769, -0.49999997, 0.49999997, 0,
0, 0.707106769, 0.707106769, 0,
-0.707106769, -0.49999997, 0.49999997, 0,
0, 0, -69.2820358, 1
_getLookAtMatrix(cameraEye, cameraAt, cameraUp):
0.707106769, 0, -0.707106769, 0,
-0.408248276, 0.816496551, -0.408248276, 0,
0.577350259, 0.577350259, 0.577350259, 0,
-35.0483475, -55.7538719, 21.520195, 1
You seem to have some serious ordering inconsistencies in your matrix class.
For example I assumed your Matrix4 constructor takes it arguments (the matrix elements) as column-major, otherwise your functions wouldn't match the reference implementations of glFrustum and gluLookAt and you would get completely screwed results.
And the code of your translate function also looks correct, since it has to modify the last column of the matrix, which are the elements (a14, a24, a34 and a44).
But the your print out of the view matrix suggests that translate actually modifies the last row, unless you print the matrix in column-major format and therefore transposed. But in this case the print of the _getLookAtMatrix suggests that the Matrix4 constructor takes its arguments in row-major order, which indeed invalidates other things.
Of course all this is also depending on how you send the matrices to OpenGL and how you use them in the vertex shader (I assume ES 2.0, otherwise there would be no need for your own matrix library). If you indeed use ES 1 then you need to send the matrix elements to OpenGL in column-major order, but the translation has to be in the last column and not the last row.
But no matter what convention you use, there is definitely a severe inconsistency inside your matrix code. But without seeing the whole Matrix4 class, the vertex shader and the code where you upload the matrices to OpenGL, it is hard to tell where this inconsistency is.
The technique shown in a similar question is a rectangular bubble. How to draw one in an oval shape? i.e.:
I would do it in two iterations.
First get the context and begin a path. Fill an ellipse and then a custom path that encloses a triangle with three lines. I assumed the following dimensions: 70 width, 62 height. Override draw rect in a subclass of UIView and instantiate in a subclassed UIViewController:
-(void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetRGBFillColor(ctx, 0.0, 0.0, 1.0, 1.0);
CGContextFillEllipseInRect(ctx, CGRectMake(0.0, 0.0, 70.0, 50.0)); //oval shape
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, 8.0, 40.0);
CGContextAddLineToPoint(ctx, 6.0, 50.0);
CGContextAddLineToPoint(ctx, 18.0, 45.0);
CGContextClosePath(ctx);
CGContextFillPath(ctx);
}
Produces this in the iPhone simulator when added against a gray backdrop:
This second code example will almost duplicate what you produced above. I implemented this using flexible sizes that could be supplied to the UIView frame when you instantiate it. Essentially, the white portion of the speech bubble is drawn with a black stroke over lay to follow.
-(void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGRect aRect = CGRectMake(2.0, 2.0, (self.bounds.size.width * 0.95f), (self.bounds.size.width * 0.60f)); // set the rect with inset.
CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0); //white fill
CGContextSetRGBStrokeColor(ctx, 0.0, 0.0, 0.0, 1.0); //black stroke
CGContextSetLineWidth(ctx, 2.0);
CGContextFillEllipseInRect(ctx, aRect);
CGContextStrokeEllipseInRect(ctx, aRect);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, (self.bounds.size.width * 0.10), (self.bounds.size.width * 0.48f));
CGContextAddLineToPoint(ctx, 3.0, (self.bounds.size.height *0.80f));
CGContextAddLineToPoint(ctx, 20.0, (self.bounds.size.height *0.70f));
CGContextClosePath(ctx);
CGContextFillPath(ctx);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, (self.bounds.size.width * 0.10), (self.bounds.size.width * 0.48f));
CGContextAddLineToPoint(ctx, 3.0, (self.bounds.size.height *0.80f));
CGContextStrokePath(ctx);
CGContextBeginPath(ctx);
CGContextMoveToPoint(ctx, 3.0, (self.bounds.size.height *0.80f));
CGContextAddLineToPoint(ctx, 20.0, (self.bounds.size.height *0.70f));
CGContextStrokePath(ctx);
}
I have another way - however I dont have any time to properly explain it.
However, my example was written in .NET for use in a Windows application.
My version creates the entire speach bubble as 2D Polygon Mesh and is partially customizable. It is a single drawn path instead of multiple parts.
While our platforms are not the same - the technique uses common math routines and procedural loop. I believe the technique could be translated to other programming languages or platforms.
Private Sub Generate(ByVal Resolution As Integer, Optional ByVal SpeachPointerAngle As Integer = (45 * 3), Optional ByVal PointerBend As Decimal = 15)
'Generated the same way we create vector (wireframe) mesh for an Ellipse but...
'... at a predefined defined angle we create
'the size of the Pointer TIP/Corner portion of the speach bubble
'in relation to the EDGE of the ELLIPSE (average)
Dim SpeachPointerSize As Integer = 30
If PointerBend > 10 Then PointerBend = 10
If PointerBend < -10 Then PointerBend = -10
'as a variable offset that should be limited to max +/- -15 to 15 degrees relative to current angle as a safe range
'- were speach pointer angle determins which side the the pointer appears
Dim PointerOffsetValue As Decimal = PointerBend
Dim ActualPointerAngle As Decimal
'SpeachPointerAngle = 360 - SpeachPointerAngle ' adjust orientation so that 0 degrees is SOUTH
'Ellipse Size:
Dim Size_X As Decimal = 80
Dim Size_Y As Decimal = 50
If Resolution < 30 Then Resolution = 30
Dim Result As Vector2()
'size of each angle step based on resolution (number of vectors ) - Mesh Quality in otherwords.
Dim _Step As Decimal = 360 / Resolution
'Our current angle as we step through the loop
Dim _CurrentAngle As Decimal = 0
'rounded values
Dim _LastAngle As Decimal = 0
Dim _NextAngle As Decimal = _Step
Dim SpeachDrawn As Boolean = False ' prevent creating more than 1 point to be safe
Dim I2 As Integer = 0 'need a stepper because of skipped IDS
'build the ellipse mesh
For i = 0 To Resolution - 1
_LastAngle = _CurrentAngle - 15
_NextAngle = _CurrentAngle + 15
ActualPointerAngle = _CurrentAngle 'side
ActualPointerAngle += PointerOffsetValue ' acual angle of point
Dim EX As Decimal = System.Math.Cos(Math.Deg2Rad(_CurrentAngle)) * Size_X
Dim EY As Decimal = System.Math.Sin(Math.Deg2Rad(_CurrentAngle)) * Size_Y
'Point extrusion size ( trying to be even size all around )
Dim ExtrudeX As Decimal = System.Math.Cos(Math.Deg2Rad(_CurrentAngle)) * (Size_X + SpeachPointerSize)
Dim ExtrudeY As Decimal = System.Math.Sin(Math.Deg2Rad(_CurrentAngle)) * (Size_Y + SpeachPointerSize)
'is Pointer angle between Last and Next?
If SpeachPointerAngle > _LastAngle And SpeachPointerAngle < _NextAngle Then
If (SpeachDrawn = False) Then
' the point for the speachbubble tip
Array.Resize(Result, I2 + 1)
Result(I2) = New Vector2(ExtrudeX, ExtrudeY)
SpeachDrawn = True
I2 += 1
Else
'skip
End If
Else
'normal ellipse vector
Array.Resize(Result, I2 + 1)
Result(I2) = New Vector2(EX, EY)
I2 += 1
End If
_CurrentAngle += _Step
Next
_Vectors = Result
End Sub
The above code generated this - drawn to a bitmap using GDI+ [DrawPolygon/FillPolygon]:
https://fbcdn-sphotos-a.akamaihd.net/hphotos-ak-ash4/380262_10151202393414692_590995900_n.jpg
(Sorry - I can't post the image here directly as I have never posted here before. I don't have the reputation yet )
This is a Primitive in a Graphics Assembly I am developing for .NET which uses my own Vector2.
This speach bubble supports transparency when drawn - as it is a single polygon shape instead of multiple shapes.
Basically we draw an ellipse programatically and then extrude a speach point out on a desired side of the ellipse.
A similar approach could be applied using PointF structures instead.
All shapes in the code are generated around Origin 0,0.
Arrays are also resized incrementally as vectors are added prevent gaps in the array.
EG - the center of the speach bubble is Origin 0.0.
I apologize for not explaining my code properly - I just don't have the time.
But it probably isnt too hard to understand.