Before this change, the two renderers both had special case code for
approximating strokes they don't support natively. This change moves
that conversion to clip.Op.Add, for several reasons:
- The compute renderer no longer need fallback logic and caches for
strokes it doesn't support.
- The approximation logic is slow. Moving it to clip.Op.Add will not
speed it up, but will make the cost easier to spot in profiles. Until all
strokes are supported natively, users can use macros to cache
expensive strokes.
- Reduced garbage: Op.Add takes an op.Ops anyway, and can use that for
storing the approximated stroke outline.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The check for path segments in gpu is redundant; clip.Op.Add doesn't add
the Path op if there were no segments.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The target of FocusOp is too subtle; be explicit instead and remove
any doubt.
Multiple SoftKeyboardOp in a single frame is rare, but if they do occur,
they should behave as if they were from separate frames: the last one
applies.
As a side-effect the key event router can be much simplified.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
It turns out restoring all operation state from the moment Defer
is executed is too much; for example, a right-click pop-up needs
the transformation, but not the current clip.
Change Defer to only restore the transformation, and reset all
other state.
Other combinations may be needed in future; we'll deal with them then,
possibly by exposing the load state mask.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Push/Pop only allows saving and restoring operation state in a
stack-like manner. We're going to need restoring arbitrary state
for implementing deferred operations.
Generalize state save/restore and implement Push and Pop on top of
that.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This CL introduces 2 new path builders:
- Outline which takes a PathSpec to be outlined
- Stroke which takes a PathSpec and a stroke style, to stroke a path.
typically, code like this:
var p clip.Path
...
p.Outline().Add(o)
should be replaced with:
var p clip.Path
...
clip.Outline{Path: p.End()}.Op().Add(o)
similarly, stroking should be modified from:
var p clip.Path
...
p.Stroke(width, clip.StrokeStyle{...}).Add(o)
to:
var p clip.Path
...
clip.Stroke{Path: p.End(), Style: clip.StrokeStyle{Width:...}}.Op().Add(o)
here are tentative 'rf' scripts (see rsc.io/rf for more details):
```
ex {
import "gioui.org/op";
import "gioui.org/op/clip";
var p clip.Path;
var o *op.Ops;
p.Outline().Add(o) -> clip.Outline{Path:p.End()}.Op().Add(o);
}
ex {
import "gioui.org/op";
import "gioui.org/op/clip";
var o *op.Ops;
var p clip.Path;
var sty clip.StrokeStyle;
var width float32;
p.Stroke(width, sty).Add(o) -> \
clip.Stroke{ \
Path:p.End(), \
Style: clip.StrokeStyle{ \
Width: width, \
}}.Op().Add(o);
}
```
Signed-off-by: Sebastien Binet <s@sbinet.org>
Previously, the only way to manipulate the clipboard (read or write) is
using the `app.Window`.
The new `clipboard.ReadOp` and `clipboard.WriteOp`makes possible to
read/write from the widget.
Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
The existing implementation cannot remove the focus of some widget,
doesn't have an option to focus without display the on-screen keyboard
and it automatically focuses the first InputOp, aggressively.
That change aims to make possible: remove focus from any widget. Add
focus without displaying the on-screen-keyboard/soft keyboard. Don't
automatically focus any widget. Don't recover focus when the widget is
visible again.
Fixes gio#180.
Signed-off-by: Inkeliz <inkeliz@inkeliz.com>
Flat and Square caps are implemented.
Bevel joins are implemented.
Round caps, Round joins and Miter joins are left for another PR.
Signed-off-by: Sebastien Binet <s@sbinet.org>
PaintOp.Rect is the wrong abstraction; it implies a clip operation
better handled by package clip, and not all paints need it (colors).
Furthermore, it's awkward to specify a PaintOp that fills up the
current clip area, regardless of its size.
Redefine PathOp to mean "fill current clip area".
API change. Replace uses of PaintOp.Rect with a TransformOp applied
before the PaintOp.
Leave a TODO for the PathOp infinity area.
Fixes gio#167
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This is effectively a revert of commit gioui.org/commit/69dfd2e3a5541.
ImageOp.Rect is the wrong abstraction; it implies a clipping operation that is
better handled by package clip.
API change. Uses of ImageOp.Rect should apply a clip.Rect before the PaintOp,
or use image.RGBA.SubImage (or similar).
Signed-off-by: Elias Naur <mail@eliasnaur.com>
Encode TransformOp as an Affince2D matrix instead and use that in gpu and io transform handling.
There are no changes to user facing API and so far only the offset part of the matrix is used.
This patch is a step towards full affine transformations.
Signed-off-by: Viktor <viktor.ogeman@gmail.com>
Converting
macro := op.Record(ops)
...
macro.Stop()
macro.Add()
to
macro := op.Record(ops)
...
call := macro.Stop()
call.Add(ops)
Which is more general (call.Add can take a different ops than the op.Record
that started it), and enforced the order between Stop and the subsequent Add.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The new field ImageOp.Rect is initialized to cover the entire source
image, but can be modified to draw only a section of it.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The ability to invoke other operation lists belongs in the new CallOp.
While we're here, make MacroOp.Add use a pointer receiver to match the
other methods.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
We'd like to improve the API of Flex, Stack and similar layouts
that use MacroOps internall. Unfortunately, the
func (m MacroOp) Add(o *Ops)
method causes the MacroOp to be allocated on the heap, ruining the
nice garbage-free property of layouts.
Fortunately, layouts don't need the feature that caused the heap
allocation: invoking operation lists different than the current.
CallOp separates the invoke-different-list semantic from MacroOp,
in preparation for removing the feature from MacroOp.
Signed-off-by: Elias Naur <mail@eliasnaur.com>
The gioui.org/commit/74407a50d598bfd27e8f8e48b6832cc5df04de77
added a NewImageOp constructor that always copies the supplied
image. It does that for two reasons:
First, the image.Image reference is used in the image=>texture
map of cached textures. Without a copy, we wouldn't detect a
modified image even if a new ImageOp was created.
Second, we don't want the program to touch the image while the GPU
is uploading it.
The second reason was removed in a previous change that blocks
FrameEvent.Frame until we're done with the operations, including
uploading images to the GPU.
The first reason is easily fixed by using a unique per ImageOp,
as pointed out by Alessandro Arzilli.
This change switches to using the unique key. Alessandro's patch
avoids the copy when possible.
Signed-off-by: Elias Naur <mail@eliasnaur.com>