Andre Poenitz wrote:

> On Tue, Oct 21, 2003 at 09:25:46AM +0000, Angus Leeming wrote:
>> Andre Poenitz wrote:
>> >> Is this just a wild flight of fancy, or does anybody else think
>> >> that it's a sensible proposal?
>> > 
>> > I think this could be handled on a case-by-case base by using
>> > some helper functions in the insets that really need it.
>> 
>> Actually, I did some reading and I think I have stumbled across
>> something very powerful.
>> 
>> The C++ streams allow us to define arbitrary new modifiers --- and
>> enable subsequent operations on the stream to be aware of them. For
>> example, the code below would be used
>>         std::ostringstream os;
>>         os << font::setFamily(font::SERIF) << "Andr? "
>>            << font::setFamily(font::SANS_SERIF) << "P?nitz\n";
> 
> I know this in theory but never managed to work with that in praxi.
> 
> I wanted to transform the different "math output stream" to a scheme
> like that at one point of time but then got distracted somehow...
> 
>> Note that it works on existing stream types!!! Thereafter one would
>> need to write a 'decipherer'. For example, something to establish
>> the width of the string in this font, or to paint it, but the
>> beauty is that this 'mark-up' is entirely separate.
> 
> Not really, is it?
> 
> You just modify some state of the stream (i.e. to "SERIF"). Than
> every write on that stream has to check this state and respond to
> it.
> 
> It is not a kind of out-of-band signalling, rather some fancy way to
> add more data room to a stream.
> 
> This safes you writing lots of 'operator<<' for the standard types
> like int, double, ... fro your custom streams, but that's it.


> And now you've got some new state in the stream object. It does not
> affect the data buffer at all. This is basically only syntactic
> sugar over
> 
>    void write(ostream & os, MyObject const &, SomeExtraData const &
>    extra)
> 
> by combining 'os' and 'extra' and re-using operator<<() for the base
> types.

My main point is that the metrics and draw routines repeat large 
blocks of code and that my separating the information from the way it 
is used we can only win.

I agree that we need to operate on the resulting data and I openly 
admit that I haven't read enough to do that. Perhaps you can help 
fill in my knowledge gap?

I imagine something like
int fontWidth(std::ostream & os) {
        int width = 0;
        std::ostream::iterator it = os.begin();
        std::ostream::iterator end = os.end();
        for (; it != end; ++it) {
                int const family = os.iword(setFamily::getAlloc())
                if (family == -1) {
                        std::cout << "Family data not set\n";
                        continue;
                }
                LyXFont font(family);
                width += (*it, font);
        }
        return width;
}

But such a stream would also allow the frontends to implement their 
own mark-up. Ie, pass a stringstream to the dialog and get bold and 
italic mark up in the right places.

Regards,
Angus


Reply via email to