Fluid 0.7.0 has been released!

IchorDev zxinsworld at gmail.com
Sat Nov 2 17:33:19 UTC 2024


On Friday, 1 November 2024 at 12:14:25 UTC, cookiewitch wrote:
> On Thursday, 31 October 2024 at 13:08:55 UTC, IchorDev wrote:
>> Sorry for my late reply! Anyway, here we go…
>>
>> [...]
>>
>> Some consideration should be given to where to start. For 
>> instance, one could build up from HarfBuzz. However, HarfBuzz 
>> is another GLib-based FSF C library, just like Pango, so 
>> perhaps this would just shift the compromises further down the 
>> line. Say we want *no* compromises; then we have to do 
>> everything 100% in D. Certainly neither of these options are 
>> trivial, and it would be a fool's errand to embark upon them 
>> alone.
>
> Thank you for dedicating your time to this, and for the very 
> elaborate response! Reimplementing PangoLayout does sound like 
> an option, but as far as I've seen, Pango operates on strings 
> all the way through. I suppose it is possible to assemble parts 
> of the rope into a string on the stack, and only operate on a 
> single part at once, but I don't think this is going to be very 
> bug-proof. Alternatively, Fluid's text engine does distinguish 
> between static and dynamic text with an "edit mode" flag, so it 
> could be possible to apply Pango on stringified static text, 
> but that's never going to be enough.

Compromises!

> Oh, and also, since Pango is LGPLv2 licensed, I think a port of 
> `PangoLayout` could run into licensing problems the way D 
> programs are usually built \[with DUB\].

If the modified source is available then I don't think that's a 
problem?

>> Having a full D text layout engine is a pet dream of mine of 
>> course, so if you're interested in contributing to a project 
>> like that then I might be able to dedicate some of my spare 
>> time to it.
>
> I've been thinking about this last week and I'm under the 
> impression this is what is going to happen anyway. For what 
> it's worth, I'm currently working on another large PR which 
> upscales Fluid's text engine, splitting it into a separate 
> `fluid.text` package and optimizing it on the way through. It 
> is mostly standalone, so if you find it appropriate, I could 
> create a new Git & DUB repository for it once I'm done. I would 
> like to have your input on it.

Sure, that sounds like a great idea!

Here are my thoughts about what could be changed based on how 
`fluid.text` is currently set up:
- `StyledText` *only* stores its strings as ropes, making it less 
ideal for static text, and not very flexible (e.g. can't use a 
custom type with fast insertion). Ideally there'd be a layout 
option for static text that uses finite forward ranges of 
`const(char)` internally for static text, and also one that uses 
a mutable string templated interface internally for user-editable 
text.
- `StyledText` only performs rendering to a texture, preventing 
it from working with renderers that use modern text rendering 
techniques, and not giving the user any control over the 
rendering pipeline. Any kind of rendering functionality should be 
separated out, and `StyledText` should provide a 
renderer-agnostic way to get all of the necessary information for 
rendering (e.g. each font glyph ID, its transformation, and 
style) as a forward range interface or similar.
- Different methods of cutting off overflowing text should be 
provided, like placing ellipses at the end of the visible text.
- You will probably want to use FontConfig (see: 
BindBC-FontConfig) by default (but ideally with an option for a 
custom implementation) to figure out what fonts each system 
prefers as fallbacks. And same story with using FreeType by 
default to load & process font data.
- `TextStyleSlice` uses a palette right now, which is pointlessly 
limited to 256 different items. It might be worth attempting to 
use a `SumType` containing each individual styling option, since 
then the defaults don't have to be re-specified with 1 exception 
every time someone uses **bold** or *italic*. Otherwise, 
`TextStyleSlice` should probably use a `size_t` for style 
indices. Also, things like colour that do not affect text layout 
should not be part of the `Style` used when making layouts in the 
first place. A user's renderer can worry about that.
- The `Typeface` interface expects implementations to have way 
too much state.
- Everything that goes into text-shaping should be accessible in 
isolation so that people who need to perform more fine-grained 
tasks can use them. For example, the bi-directional algorithm.
- The styling needs to be known when generating a layout, and it 
might be desirable for the layout to be lazily re-computed.

So all in all, a bit like this example:
```d
alias LayoutStyle = SumType!(
	FontFace, Padding, TextDirection,
	Alignment, Justify, /+et cetera+/
);
struct LayoutStyleRange{
	size_t from, to;
	Style style;
}

struct Caret{ Vec2!float pos; float height; }

mixin template SharedTextLayoutStuff(Text){
	Text text;
	RedBlackTree!(LayoutStyleRange, ".from", true) styleRanges; 
//styles are sorted by `.from` for efficiency
	uint textSerialNumber; //to see if text was updated
	
	///calculates the layout. Called when `textSerialNumber` is no 
longer current by anything that uses the layout (e.g. 
getRenderData)
	void calculate();
	
	///gets data used for rendering the glyphs
	SomeForwardRange!GlyphRenderData getRenderData();
	
	//more functions...
	
	///the position & height of a caret at a certain string index
	Caret getCaret(size_t ind) const;
	///the string index of a caret at a certain visual position
	size_t getIndex(Vec2!float pos) const;
}

///rarely changes, uses string-like forward ranges
struct TextLayout(Text)
if(IsSomeFiniteCharRange!InternalText){
	mixin SharedTextLayoutStuff!(InternalText);
	
	//static-specific stuff
}

///changes with random insertion and deletion, uses an abstract 
interface
struct DynamicTextLayout(Text)
if(
	isDynamicLayoutText!Text
	//`Text` needs at least:
	//a forward range interface (empty, popFront, front)
	//opIndex
	//opIndexAssign with overloads for slicing
	//insertion & deletion
	//a number that is incremented every time it is updated
){
	mixin SharedTextLayoutStuff!(Text);
	
	//dynamic-specific stuff
}
```


More information about the Digitalmars-d-announce mailing list