[cairo] Circular Ring Gradient

Olaf Schmidt ng at vbRichClient.com
Sun May 14 00:03:19 UTC 2017

Am 11.05.2017 um 01:08 schrieb cecashon at aol.com:

> Still stuck with the problem of starting and stopping a gradient in an arc at discrete points in the arc. I haven't figured out how to "sweep" a gradient color through a ring arc in a smooth fashion. That would make a gauge widget a little more adjustable wirh a standardized scale.

FWIW, ... what I'm using for years (for "conical stuff") is based
on cairo-functionality, which existed already before the mesh-patterns
were introduced.

It's a short and simple function, which allows (in the arguments
StartDeg, and DistDeg), to specify also a Start-Angle and an
Angle-Distance (in degrees).

'---- VBScript-Code, based on the cairo-COM-wrapper for Windows ----

Function CreateRingSrf(Size, Radius1, Radius2, StartDeg, DistDeg, SpArr)
Dim Steps, Pat, i
     Steps = Size * DistDeg / 360 * Cairo.PI * 2

     Set Pat = Cairo.CreateLinearPattern(1, 0, 2 * Steps - 1, 0)
     For i = 0 To UBound(SpArr)
       Pat.AddColorStop i / UBound(SpArr), SpArr(i)

     With Cairo.CreateSurface(Size, Size).CreateContext
       .SetLineCap 1 '<- 1 = CAIRO_LINE_CAP_ROUND
       .SetLineWidth 1.35

       .TranslateDrawings Size / 2, Size / 2
       .RotateDrawingsDeg StartDeg + DistDeg / Steps * 0.5 - 90
       Set Pat.Matrix = Pat.Matrix.TranslateCoords(1, 0)
       For i = 1 To Steps
         .MoveTo 0, Radius1 + .GetLineWidth
         .LineTo 0, Radius2 - .GetLineWidth
         .Stroke 0, (Pat) '<- Stroke with a shifted Source-Pattern
         .RotateDrawingsDeg DistDeg / Steps
          Set Pat.Matrix = Pat.Matrix.TranslateCoords(2, 0)

       Set CreateRingSrf = .Surface 'return the Surface to the caller
     End With
End Function

Dim Cairo: Set Cairo = CreateObject("vbRichClient5.cConstructor").Cairo
Dim SpArr: SpArr=Array(vbRed, vbYellow, vbGreen, vbCyan, vbBlue, _
                               vbYellow, vbGreen, vbCyan, vbRed)
CreateRingSrf(300,60,120,0,360,SpArr).WriteContentToPngFile "RingCon.png"

'---- end of VBScript-Code ----

The above will produce basically the same thing as the other examples:
... and it should be translatable to the C-Flat-API quite easily.

When I use this stuff in a gauge-widget, I'm calculating the
Conical-Surface once for the given WidgetSize - and then use
it as the SourceSurface, doing a simple Arc + Stroke on that
(unchanging) Source with a proper LineWidth.

So, to calculate a "Cold-to-Hot" Gauge-Scale, which range-wise covers
two/thirds of the full-circle when at 100%, you would use the above
function with the following Parameters:

Const StartDeg = 60 + 90, DistDeg = 240 '<- 2/3 of a full circle

SpectArr = Array(vbCyan, vbBlue, vbMagenta, vbRed, vbYellow)

Set RingSrf = CreateRingSrf(240, 70, 90, StartDeg, DistDeg, SpectArr)
     RingSrf.WriteContentToPngFile "GaugeScale.png"

Producing: http://vbRichClient.com/Downloads/GaugeScale.png



More information about the cairo mailing list