Open ccoupe opened 8 years ago
Now that I've done some looking around in the deep parts of Shoes, I think adding a 'chars_at' method to image would be better, name wise. Less confusion with text and string. Cairo does have a cairo_show_text(string) method so it seems possible. Not simple, but very possible.
i think this is a great idea, When you have a long text (not that long) it quickly kills shoes performance because of all those active objects that shoes have to redraw again and again, just scrolling becomes a pain. As we can't actually edit the text (it's possible but not fully implemented) there is less use for live text objects... Maybe it's possible to keep live objects for resizing and a pixels data for scrolling for example ? a buffer with all text and attributes ready to be re-rendered when resizing, but silent for cases where re rendering would be unnecessary ...
I like the concept too. I'm not so keen on the method name. Cairo-wise it's pretty straight forward task since we know how to render text to. Dealing with font would be a lot easier if Shoes had a font class but it doesn't (it's more like a module.function) Pangocairo is reasonably simple but bit wordy.
I suspect the facility has many use cases - how would one draw the labels of a pie chart using flows and stacks or put text inside the wedges. Maybe somebody wants to watermark or annotate an image. Lots of interesting things and as you mention if you build them out of a new or hidden textblock that would be very clever. I suspect @dredknight would find some uses.
I may end up creating a small group of C pangocairo routines in the next day or so since #264 will need them. @passenger94, if you want to work on this issue instead of new ruby-c macros let me know (or assign the issue to yourself). I've got plenty of things to do.
i'm looking into this, we'll see :-)
i'm trying to understand the plot plumbing and where are the pangocairo routines ... (i think i got the general view, now onto deep immersion)
if i understand correctly, you want to switch to pango for the text rendering there ?
hehehe :). Thanks @ccoupe. I will be happy to see some examples on how this method is presented on the canvas.
Plot only draws text in a few place and as currently written recomputes text heights and widths far too often, values that could be precomputed and cached for shoes_plot_draw to find. The cairo toy interface has problems with some languages/character-sets - for US/UTF-8 - it's fine but that's not everything in the world. I don't expect a lot of trouble, I hope to have it done when you awake in the morning. See:
ok :-)
did you know :
Shoes.app do
shape width: 100, heigth: 50 do
transform :corner
translate 20, 20
scale 2.5
skew 15.0, 20.0
rotate -25
para "deep transformed text\ntransformed deep text"
end
end
Doesn't work in image block, too bad :-D
after some hacking around for the sake of it, an image text block :
works but it means adding a lot of methods to cImage (para, title ... potentially span, strong, etc..) and adding the transform methods to textblock and the text is still alive, which is kinda fun but not what we are after ! Probably ugly to manipulate, also.
Though, simply adding the transform methods to textblocks could be something to think about (dead simple : one only needs to create them with a call to the appropriate Macro and make ruby aware of them)
and yes it keeps styles after the transformation ! ... maybe oblique text in legends or the like ...
back to reach for some pixels out of text ...
Wow! I just knew there had to be existing way to get text into a shape. You found it!
Thinking out loud: perhaps a textblock.to_shape
and/or textblock.to_image
method would be the way to go?
On the shape side the functionality is there, one just need to use it, no special method is necessary, or do you feel a cleaner API would be a good idea ?
As for the image block, i first thought it was not worth the resulting noise in the api, as text is still alive that way, but, in my experimentations for fetching pixels out of a texblock, i realized that it's easy to just hijack the text drawing process and render to an independent surface, but then what ? ok we've got pixels but if we simply re-render that surface in lieu of the normal text rendering, the result is exactly the same : alive text which redraws every time a drawing is triggered. So, once i have a surface from the textblock, i'm thinking now to pipe into the image processing because of the embedded cache mechanism (means files created, potentially a lot, viable with RED warnings ??) ... if this doesn't work maybe the image block becomes an option to play with... On a second thought if we have big amount of texts we want to pixellize so it doesn't redraw again and again, image block or something similar would be a good way to materialize the peculiarity of that text block ...
Another option is to mark the text block as special (say rendered) and make it skip subsequent drawings but one need to keep placement functionality effective ... let's see hmmm no, stupid idea !! :sunglasses: But interesting question : as Shoes is endlessly redrawing everything, how does one guard some parts from beeing redrawn but yet still vsible ... (and at the appropriate place) ?
At this point I vote for the easy way and then see how well it works or how hard it is to use. I think just creating a new shape type like arc or oval which is just a rectangle with some extra style args for the string, font choice for creation. Rendering the string into the rectangle via cairo drawing into simple surface - https://www.cairographics.org/manual/cairo-Image-Surfaces.html. Of course we'd need a place to keep the cairo_surface ptr. It is not a Shoes image as we know them. It would share all methods that shapes respond to. That was the simple idea but I only did enough research to think it ought to work. It would need to work when combined into a container shape.
This is essentially what is going on now : textblock is just a special shape, which happens to be precomputed in a pango layout but lastly rendered in a cairo context (it even explicitly use some Shoes shape methods in C code). That's also why the text in a shape block works out of the box but not in an image block (those 2 are different beast, one need to add redirection facility to make it work on image blocks). Again, i'm able to render the text in a separate ImageSurface (controlled via an attribute in Shoes - ruby code -) and show that surface instead of directly the pango layout, but there is no point to do so unless we can cache the imageSurface, Redrawing is going to happen anyway (ideally the cache would be redrawn, at least theoretically we can skip subsequent pango calculations, nothing more - maybe more memory efficient ? - ) and i'm not even talking about placements whose computation is deeply tied/mixed/interleaved with pure pango/cairo drawings ... Right now the only solution i can think of, once an ImageSurface is drawn out of a textblock, is to make it, if possible, an Image object so it can be properly placed and the cache facility used
What i have now: gray background is a cairo.paint() on the ImageSurface to get visual feedback
para "rendered para ! does it go outside of the window if " \
"i write a long text or does it wrap and begin a new line ?",
render: true, stroke: blue
That thing is still live text, it wraps and length changes on resizing (until ImageSurface dimension is hit, in which case, of course, text disappears, another thing to manage ...)
proof of concept :
rendering a textblock on a separate ImageSurface, if asked to do so, create a new cImage object, replace the cached_image surface of the cImage object with the one created from the textblock (maybe we can shrink this to a cached image only ...) reuse the cached surface for subsequent drawings ... (good news is apparently the cache is on memory, no files!)
Now the text is fixed at the "shape" it had at the first drawing
going to experiment to see how it behaves with other objects on the canvas, expecting troubles ....
ok i polished the thing, it's working ... well i have not explored every aspect of it because i hit one severe restriction : images and text don't mix correctly (i mean even in a regular Shoes app) in a flow at least, kind o a big mess ...
Shoes.app do
para "some text "
# hybrid = para "rendered para ! does it go outside of the window if " \
# "i write a long text or does it wrap and begin a new line ? that part should disappear when not wrapped",
# render: true, stroke: blue, margin: [20,20,20,20]
hybrid = image "PATH/TO/YOUR/IMAGE"
self.start { |slot|
para "another text", stroke: green
para "\nself.contents[] #{slot.contents.inspect}, responds to :highlight ? #{hybrid.respond_to?(:highlight)}" \
" , responds to :blur ? #{hybrid.respond_to?(:blur)}"
para "\nself.contents[1] #{slot.contents[1].inspect}, responds to :highlight ? " \
"#{slot.contents[1].respond_to?(:highlight)} , responds to :blur ? #{slot.contents[1].respond_to?(:blur)}"
para "hybrid size : #{hybrid.width}, #{hybrid.height}"
}
end
also the start block necessary to be able to fetch updated info like image size, etc...
That demo makes creating a shape with explictit(l,t,h,w) much more appealing since they don't appear don't fit into slots or flows either.
Agree ! Adding an entry to Shape or textblock in manual seems the best refactorization avalaible!
I created a new text_shape branch, local and remote and after much head scratching it's also the best method name(IMO) to add to Shoes. In concept it's just like oval or star with some new arguments at creation. Since shapes don't respect flow/stack/slot layouts, it's of limited value.
From #294
Does text_shape support anti-aliasing? (Maybe we should move this conversation to #266)
Shoes does all char/string drawing with pangocairo (except, perhaps, some osx native control labels and dialogs) text_shape would be no different that normal Shoes behavior. You can reading the pango, cairo and pangocairo docs online if you want to know what can be done.
From #264, Shoes could have a new text_shape slot art method. A rendered string so it's just pixels, no string modifications allowed after creation. but the pixmap could be positioned and transformed like any other Shoe Art like oval or star.
creates a 50px X 20px box and renders the text: string into it. In this example it would clip, truncate, deform and make a dogs mess of it. That's a user problem. Shoes just has a 50w X 20h block of pixels to deal with. Defaults would be tricky - without a width and height they would default to the rect that contains the complete string in [given] font. We'll want foreground (text) and background color so that some more :option strings to deal with.
Most of the work would appear to be canvas.c, ruby.c and perhaps image.c so obj-c skills would not be required. Discuss.