Offset uniqueness in vector of ColorSteps

Armin Le Grand armin_le_grand at me.com
Wed Mar 15 10:20:02 UTC 2023


Hi Regina,

thanks for the points, will comment inline

On 3/14/23 23:07, Regina Henschel wrote:
> Hi Armin,
>
> Armin Le Grand schrieb am 14.03.2023 um 15:08:
>> Hi Regina,
>>
>> good to hear from you, wanted to contact you already anyways, but we 
>> were just moving, so I was pretty busy :-)
>>
>> On 3/14/23 14:09, Regina Henschel wrote:
>>> Hi Armin,
>>>
>>> you put the ColorSteps into a sorted vector with unique offsets of 
>>> the ColorSteps.
>>>
>>> I see a problem with "unique". Both OOXML and SVG allow several 
>>> color stops to have the same offset. Users need it in OOXML and SVG 
>>> gradients to create stepped gradients like those from ODF 
>>> draw:gradient.
>>>
>>> Thus forcing uniqueness in our core will give problems in import 
>>> filter and in implementing the <svg:radialGradient> and 
>>> <svg:linearGradient> from ODF.
>>
>> Very good hints, thanks for that.
>>
>> Indeed I thought about having two (or more) identical ColorStops to 
>> allow a 'rapid' color change at the same offset. I abandoned that by 
>> thinking that a very small step could be used that will never get 
>> visible, so e.g.
>>
>>    0.5
>>    0.5000001
>>
>> But allowing multiple identical may express that indeed better.
>>
>> The problem is and why I chose uniqueness is also/mainly the UI - how 
>> to represent equal ColorSteps in a UI trying to visualize the 
>> ColorSteps...?
>
> The UI could have a sorted list (drop-down?) of gradient stops, so 
> that it is possible to select a gradient stop without using the mouse. 
> Then fields for position, color and maybe transparency will act on the 
> selected gradient stop.
> But that would be a question for the UX-team.


Yes, I already discussed on FOSDEM with Heiko, so it's initiated (we 
discussed about that anyways for years :-)). Fact is that UI is far 
away, 1st need to get that working in the core & im/exports. Of course 
an intuitive graphical visualization with added interactions would be 
preferrable to a list view - just my 2ct - but list view may be 1st shot 
later...


>
> Export to OOXML writes 0.5 as 50000, thus 0.5000001 would be written 
> as 50000 too. If you want uniqueness, the import filter would need to 
> consider that. I have not looked what conversion from and to SVG does.


Yes, that was only a 'guessed' example. In that case and knowing that 
keeping a small distance is needed due to it's meaning/definition of 
course 50000/50001 would have to be used, an export filter would have to 
be aware of that 'special' value. Note: no, I do *not* like special 
values, but...


>
>>
>> So:
>>
>> - It should then be OK to have a maximum of *two* ColorStops with 
>> identical offset?
>
> I think that could work in common use cases. But the gradient stops 
> will be available for macros and I don't know what funny things users 
> do in macros. And I do not know enough about SMIL in ODF to say what 
> animations are theoretically possible.
>
>>
>> - When correcting that, and there are more than two, delete all but 
>> 1st and last? So the in-between ones?
>
> MS Office keeps them. You can traverse the gradient stops with the 
> arrow keys in the UI of MS Office.
>
>>
>> - Also dependent of used colors: if all the same color, identicals 
>> can be deleted, so go to uniqueness.
>
> That would indeed not be visible in rendering and might ease 
> searching. But here too, how react on using gradient stops in macros?
>
>>
>>
>> And Questions for ODF format:
>>
>> I see e.g. in SVG something like
>>
>> <linearGradient id="Gradient2" x1="0" x2="0" y1="0" y2="1">
>>        <stop offset="0%" stop-color="red" />
>>        <stop offset="50%" stop-color="black" stop-opacity="0" />
>>        <stop offset="100%" stop-color="blue" />
>> </linearGradient>
>>
>> so I would just add elements like
>>
>>        <stop offset="0%" stop-color="red" />
>>
>> to our ODF, is that OK from your POV? I remember we once discussed 
>> that already, so should be no problem to do that I guess?
>
> For ODF you need to distinguish <draw:gradient> from 
> <svg:linearGradient> and <svg:radialGradient>.
>
> The relationship between <svg:linearGradient> and <svg:radialGradient> 
> to your ColorSteps vector is indeed straight forward. Only the 
> com::sun::star::util::Color has to be split in svg:stop-color with 
> #RRGGBB and svg:opacity calculated from alpha.
>
> Using your concept with a stop containing {double Offset, 
> com::sun::star::util::Color Color} does not work well for 
> <draw:gradient> because StartColor and EndColor in <draw:gradient> are 
> without alpha. To get transparency you always need parallel a 
> <draw:opacity> element.
>
> Having separate <draw:gradient> and <draw:opacity> elements in ODF 
> allows to have gradients with e.g. color change from left to right and 
> transparency changing from top to bottom. That cannot be expressed 
> with one sequence of your new ColorSteps vector.
>
> Further problems are the relationship between your ColorSteps vector 
> and the attributes draw:border and draw:step-count.


Yes, we cannot change our stuff too far to get to svg definitions - we 
will not get rid of these. We will also not have a svg:spreadMethod. The 
currently important point is to use existing svg definitions (to not get 
even further away from svg as needed) as far as possible, as far in 
their svg meaning as possible, too.

For now we need to get the Color-Stops added to 'our' gradients. Do you 
have concrete examples/advice how to do that?


>
>>
>> I would take out from this the StartColor (AKA offset == 0.0) and the 
>> EndColor (AKA offset == 1.0), so in the normal case there would be no 
>> change at all. >
>> If there are ColorSteps with offset != 0.0 or 1.0 I would create that 
>> extra-entries for these.
>
> What do you mean by "take out"?


Just that for 0% I would use our draw:start-color and for 100% our 
draw:end-color. I would only write new entries in svg-conform semantic 
for offsets ]0%..100%[. This is to stay as compatible as possible. It 
also makes no sense to 'double' the information with having the same 
color represented e.g. for StartColor once as draw:start-color and once 
as <stop offset="0%"/>.


>
>>
>> Currently we have something like
>>
>> <draw:gradient draw:name="Gradient_20_2"
>>      draw:display-name="Gradient 2" draw:style="radial" draw:cx="50%" 
>> draw:cy="50%"
>>      draw:start-color="#bf0041"
>>      draw:end-color="#127622"
>>      draw:start-intensity="100%" draw:end-intensity="100%" 
>> draw:border="0%"/>
>>
>> which would then be something like
>>
>> <draw:gradient draw:name="Gradient_20_2"
>>      draw:display-name="Gradient 2" draw:style="radial" draw:cx="50%" 
>> draw:cy="50%"
>>      draw:start-color="#bf0041"
>>      <stop offset="0%" stop-color="red" />
>>      draw:end-color="#127622"
>>      draw:start-intensity="100%" draw:end-intensity="100%" 
>> draw:border="0%"/>
>
> That do not work for formal reason: You cannot mix attributes and 
> elements.
> But in a first step, the line <stop offset="0%" stop-color="red" /> is 
> not needed at all. On writing the markup the values of 
> draw:start-color and draw:end-color are calculated from the first and 
> last gradient stop. These gradient stops need not be at 0% or 100% 
> respectively, because the colors are continued to 0% or 100%. On 
> reading the markup the gradient stops at 0% and 100% are calculated 
> from start-color and end-color.
>
> The main task should be to use multi-color gradients to implement the 
> two svg-gradient types. And change the import and export filter with 
> OOXML to use them for gradFill "lin" and to use them for converting 
> from and to SVG. That would be already a great step forward for most 
> users. We could even use them for the other OOXML gradFill types, 
> although that still makes them not fully compatible with our gradients.
>
> In a second step we can think about bringing multi-color gradients to 
> <draw:gradient>. That includes how to handle transparency, border and 
> step-count. It might be, that it is easier to introduce new types of 
> gradients for <draw:gradient> than to change the existing ones. Or 
> even add a new gradient element. We cannot do without <draw:gradient> 
> because all types but "linear" and "axial" are not representable with 
> svg-gradients.


I disagree here. To get forward for now the easiest would just be to 
'somehow' add the Color-Steps which are not Start/EndColor in a 
as-svg-compatible way as possibe to 'our' gradients for now. The 'other' 
possibility is (unfortunately) not backed, so when we want that in odf 
we need the simple way 1st definitely...

The replacement/mapping step to get them moved to the two SVG types 
is/will be much more complicated. I agree that four could be mapped, but 
I also agree that lots of our old attributes (not only border and 
step-count). A short hint for transparency - we can just do that on a 
higher level by adding a TransparencyGradient to objects that need them 
with the same gradient definition - that will work. You can easily 
create an example in draw, create an object with gradient, choose to 
also have a transparency gradient, put the values to the same values and 
you get controllable transparency in the same granularity as the 
gradient itself.


>
>>
>> For import of 'older' stuff all will be good.
>>
>> For import of new stuff in older Offices we would fallback to 
>> Start/EndColor and ignore the In-Between steps - any ways the best we 
>> can do AFAIS.
>
> Yes, see above.
>
>
> A further remark: We have in the meantime "Theme Colors". LO7.6 does 
> not yet save theme colors to <draw:gradient>. But you can already have 
> a solid fill with a theme color combined with a transparency gradient. 
> Do you have already ideas about "Theme Colors" in gradients? Such is 
> needed for roundtrip with OOXML.


Not yet, but thanks for the hint, will keep a note in my mind - one 
after the other..


>
> Kind regards,
> Regina

Kind regards back,
     Armin


-- 
--
ALG (PGP: EE1C 4B3F E751 D8BC C485 DEC1 3C59 F953 D81C F4A2)



More information about the LibreOffice mailing list