Text in Konva Custom Shape - konvajs

I need text output from my Custom Shape.
My code:
sceneFunc(context, shape) {
context.strokeStyle = "black";
context.font = (15 / shape.parent.scale().x).toFixed(0) + "px arial";
context.textBaseline = 'middle';
context.textAlign = 'center';
context.fillStyle = 'red';
context.beginPath();
context.strokeText("AAABBBCCC", shape.attrs.centerPoint.x, shape.attrs.centerPoint.y);
context.closePath();
context.fillStrokeShape(shape);
}
The text is properly rendered, but it is not filled. How can I fill the text?
Text output

Konva can't automatically fill/stroke text, because the text is using slightly different methods for drawings.
If you want to draw text in custom shape, you don't need to use context.fillStrokeShape(shape);. Just draw what you want in sceneFunc. Use context.strokeText() and context.fillText().
Then manually create a hit graph (using rectangle) in hitFunc. For hit demo take a look here: https://konvajs.org/docs/events/Custom_Hit_Region.html#1-What-is-hitFunc

Related

Metal alphaBlendOperation .max weird behavior

I'm using metal to draw some lines, my drawing canvas has a texture in MTLRenderPassDescriptor and when I draw inside it blending is enabled MTLRenderPipelineDescriptor and I'm using alphaBlendOperation = .max
renderPassDescriptor = MTLRenderPassDescriptor()
let attachment = renderPassDescriptor?.colorAttachments[0]
attachment?.texture = self.texture
attachment?.loadAction = .load
attachment?.storeAction = .store
let rpd = MTLRenderPipelineDescriptor()
rpd.colorAttachments[0].pixelFormat = .rgba8Unorm
let attachment = rpd.colorAttachments[0]!
attachment.isBlendingEnabled = true
attachment.rgbBlendOperation = .max
attachment.alphaBlendOperation = .max
I can change the properties in brush (size, opacity, hardness "blur"). However first two brushes are working really great as in the image bellow
But I have only one weird behavior when I use blurred brush with faded sides where lines are connected the faded areas is not blending as expected and an empty small line created between the connection. the image bellow described this issue, please check the single line and single point and then check the connections you can see this behavior very clear
MTLRenderPassDescriptor Should choose even the bellow alpha from down texture or brush alpha but when tap in the second and third point its making empty line instead of choosing a one of the alpha, Its like making alpha zero in these areas.
This is my faded brush you can see there is a gradian of color but i don't know if there is a problem with it
Please share with me any idea you have to solve it

Konva - visualize custom hit area

Is there an easy way to visualize a custom hit area shape?
As described here
https://konvajs.github.io/docs/events/Custom_Hit_Region.html
the hitFunc attribute can be set to a function that uses the supplied context to draw a custom hit area / region. Something like this:
var star = new Konva.Star({
...
hitFunc: function (context) {
context.beginPath()
context.arc(0, 0, this.getOuterRadius() + 10, 0, Math.PI * 2, true)
context.closePath()
context.fillStrokeShape(this)
}
})
For debugging purposes, I would like an easy way to toggle visual rendering of the shape (circle in this case), eg by filling it yellow.
Thanks :)
Currently, there is no public API for that. But you still can add hit canvas into the page somewhere and see how it looks:
const hitCanvas = layer.hitCanvas._canvas;
document.body.appendChild(hitCanvas);
// disable absolute position:
hitCanvas.style.position = '';
http://jsbin.com/mofocagupi/1/edit?js,output
Or you can add hit canvas on top of the stage and apply an opacity to make scene canvases visible:
const hitCanvas = layer.hitCanvas._canvas;
stage.getContainer().appendChild(hitCanvas);
hitCanvas.style.opacity = 0.5;
hitCanvas.style.pointerEvents = 'none';
http://jsbin.com/gelayolila/1/edit?js,output

How to add an image in display.newCircle() in corona SDK

I want to change the color of a circle with a custom image. Is it possible to do so?
Yes it is possible. Try
-- Create a vector rectangle
local circle = display.newCircle( 200, 200, 300 )
-- Set the fill (paint) to use the bitmap image
local paint = {
type = "image",
filename = "texture1.png"
}
-- Fill the circle
circle.fill = paint
More information you can find in documentation.

Undesired End-Caps with StrokeStyle when using PathGeometry.Widen()

I'm using SharpDX in order to draw polylines on .NET WinForms.
These polylines represent the profile of sheetmetal.
A PathGeometry object is composed, defining the polyline:
'reset m_pathGeometry (the core geometry of this sheetmetal profile)
m_pathGeometry = New PathGeometry(D2DCanvas.canvas_factory2D)
' pointsRef = collection of points showing the segments & bends in this sheetmetal profile
Dim pointsRef As List(Of Vector2) = calculateSegmentsPoints()
' Add lines to m_pathGeometry using our points collection
Using sink As SimplifiedGeometrySink = m_pathGeometry.Open()
sink.BeginFigure(pointsRef.First(), FigureBegin.Filled)
sink.AddLines(pointsRef.ToArray)
sink.EndFigure(FigureEnd.Open)
sink.Close()
End Using
Before being drawn to screen I apply a transform (to take into account transformation & scale):
' update m_fillTransformedGeometry based on m_pathGeometry & the current transform matrix3x2,
m_fillTransformedGeometry = New TransformedGeometry(D2DCanvas.canvas_factory2D, m_pathGeometry, Matrix3x2.Rotation(m_rotation, InsertPoint) * _transformMatrix)
' to draw the polyline
D2DCanvas.canvas_renderTarget2D.DrawGeometry(m_fillTransformedGeometry, m_fillBrush, plaatdikte * _transformMatrix.ScaleVector(1), m_strokeStyle)
The polyline gets drawn with a strokestyle, rounded line-joins and flat end-caps
With m_strokeStyleProps
.LineJoin = LineJoin.Round
.EndCap = CapStyle.Flat
.StartCap = CapStyle.Flat
End With
Result is a bit pale, could use a stroke:
First idea was to draw the same polyline in a darker color, with a slightly wider StrokeWidth:
' First draw a wider stroke
D2DCanvas.canvas_renderTarget2D.DrawGeometry(m_fillTransformedGeometry, m_strokeBrush, (plaatdikte + 0.2) * _transformMatrix.ScaleVector(1), m_strokeStyle)
' Then draw the fill
D2DCanvas.canvas_renderTarget2D.DrawGeometry(m_fillTransformedGeometry, m_fillBrush, plaatdikte * _transformMatrix.ScaleVector(1), m_strokeStyle)
The result is nice, but the end-caps don't get a stroke this way:
Second idea is to create a (slightly widened) PathGeometry for the stroke itself by calling the Widen() method on the original polyline-PathGeometry.
'define m_widenedPathGeometry (makes op the outline/stroke of this sheetmetal profile)
m_widenedPathGeometry = New PathGeometry(D2DCanvas.canvas_factory2D)
Using sink As SimplifiedGeometrySink = m_widenedPathGeometry.Open()
m_pathGeometry.Widen(0.2, sink)
sink.Close()
End Using
This widened geometry gets drawn (taking in account transformation) as a 'stroke' prior to drawing the 'fill' (both using the same StrokeStyle!):
' update m_transGeom based on m_widenedPathGeometry & the current transform matrix3x2,
m_transGeom = New TransformedGeometry(D2DCanvas.canvas_factory2D, m_widenedPathGeometry, Matrix3x2.Rotation(m_rotation, InsertPoint) * _transformMatrix)
' to draw the stroke of the Polyline
D2DCanvas.canvas_renderTarget2D.DrawGeometry(m_transGeom, m_strokeBrush, plaatdikte * _transformMatrix.ScaleVector(1), m_strokeStyle)
' update m_fillTransformedGeometry based on m_pathGeometry & the current transform matrix3x2,
m_fillTransformedGeometry = New TransformedGeometry(D2DCanvas.canvas_factory2D, m_pathGeometry, Matrix3x2.Rotation(m_rotation, InsertPoint) * _transformMatrix)
' to draw the fill of the PolyLine
D2DCanvas.canvas_renderTarget2D.DrawGeometry(m_fillTransformedGeometry, m_fillBrush, plaatdikte * _transformMatrix.ScaleVector(1), m_strokeStyle)
This generates an undesired effect on the End-Caps:
(Either rounded, wich isn't defined in the StrokeStyle or something in between)
This Stroke/Fill - method kindof works correctly when I redefine the used StrokeStyle to have 'rounded' endcaps:
But the 'flat' end-caps is really what I'm after.
Any ideas why this is happening, or how I could tackle this differently ?
Cheers !
Found out what was wrong here!
Writing this down for others that might encounter something similar to this.
When creating the widened geometry i've added that the 'FigureEnd' property is set to 'Open', this prevents the geometry of creating a 'closed loop' on itself, wich results in those artifacts.
m_widenedPathGeometry = New PathGeometry(D2DCanvas.canvas_factory2D)
Using sink As SimplifiedGeometrySink = m_widenedPathGeometry.Open()
m_pathGeometry.Widen(0.2, sink)
**sink.EndFigure(FigureEnd.Open)** <- adding this line leaves the stroke open!
sink.Close()
End Using

Draw custom shadow on label

I'm trying to achieve this kind of shadow, my research led me to using the CGPathRefto draw the shadow myself, but I can't figure out how it actually works.
Drawing the label.layer.shadowPath looks like a good plan, can anyone show me/point me to how I should proceed?
EDIT : I'm now to the point of trying to draw a UIBezierPath based on the string in the current label, the path being the actual shape of the shadow I need. I'm not sure that's the best option but it looks more promising.
EDIT 2 : Here is the code i'm now working with. this outlines the text of the label as an image, but it's pretty much the exact same text as the label itself, i still have to work my way around making it look like a shadow. Note, we're using Xamarin
public override void Draw (CoreGraphics.CGRect rect)
{
base.Draw (rect);
using (CGContext g = UIGraphics.GetCurrentContext ()) {
UIBezierPath completePath = UIBezierPath.Create ();
g.ScaleCTM (1, -1);
g.TranslateCTM (2, -(this.Bounds.Height / 2) - (this.Font.LineHeight / 3));
CTLine line = new CTLine (this.AttributedText);
CTRun[] runs = line.GetGlyphRuns ();
for (int i = 0; i < runs.Length; i++) {
CTRun run = runs [i];
CTFont font = run.GetAttributes ().Font;
for (int j = 0; j < run.GlyphCount; j++) {
NSRange currentRange = new NSRange (j, 1);
CGPoint[] positions = run.GetPositions (currentRange);
ushort[] glyphs = run.GetGlyphs (currentRange);
CGPath letter = font.GetPathForGlyph (glyphs [0]);
CGAffineTransform transform = CGAffineTransform.MakeTranslation (positions [0].X, positions [0].Y);
CGPath path = new CGPath (letter, transform);
UIBezierPath newPath = UIBezierPath.FromPath (path);
completePath.AppendPath (newPath);
}
}
completePath.LineWidth = 1;
UIColor.Red.SetStroke ();
UIColor.Blue.SetFill ();
completePath.Stroke ();
completePath.Fill ();
completePath.ClosePath ();
//Here I will try to loop over my current points and go down & right at every step of the loop, see how it goes performance-wise. Instead of one complex drawing I'll just have a very simple drawing that has thousands of points :o
g.AddPath (completePath.CGPath);
g.DrawPath (CGPathDrawingMode.FillStroke);
}
There is no built in way to achieve this effect. You have to implement the drawing code on your own.
Here are two ideas to create the shadow:
Draw the text in dark blue color, repeated n times, starting from the original position in 0.5 pt. steps shifted down right. This has bad performance but is really easy to implement.
Find the text outline using Core Text and implement some algorithm that creates the actual outline of the shadow. This could then be used as the shadowPath property.

Resources