Microsoft Small Basic

Program Listing: VNX976
' Subtractive Color
' Copyright © 2016 Nonki Takahashi. The MIT License.

GraphicsWindow.Title = "Subtractive Color"
gw = 598
gh = 428
GraphicsWindow.Width = gw
GraphicsWindow.Height = gh
GraphicsWindow.BrushColor = "White"
GraphicsWindow.FillRectangle(0, 0, gw, gh)
param = "x=200;y=50;size=200;color=#00FFFF;" ' Cyan
SubCircle()
param = "x=150;y=137;size=200;color=#FF00FF;" ' Magenta
SubCircle()
param = "x=250;y=137;size=200;color=#FFFF00;" ' Yellow
SubCircle()

Sub SubCircle
r = param["size"] / 2
cx = param["x"] + r
cy = param["y"] + r
subColor = param["color"]
For y = Math.Round(cy - r) To Math.Round(cy + r)
_x = Math.Round(Math.SquareRoot(r * r - (cy - y) * (cy - y)))
x = cx - _x
width = 2 * _x
GetLine()
SubLine()
EndFor
EndSub

Sub GetLine
' param x, y - left end position of the line
' param width - of the line
' return seg - segment array for the line
seg = ""
iSeg = 0
For _x = x To x + width - 1
color = GraphicsWindow.GetPixel(_x, y)
If seg[iSeg]["color"] <> color Then
iSeg = iSeg + 1
seg[iSeg]["color"] = color
seg[iSeg]["x"] = _x
seg[iSeg]["y"] = y
seg[iSeg]["width"] = 1
Else
seg[iSeg]["width"] = seg[iSeg]["width"] + 1
EndIf
EndFor
EndSub

Sub SubLine
' param seg - segment array for a line
' param subColor - color to subtract
nSeg = Array.GetItemCount(seg)
index = Array.GetAllIndices(seg)
color2 = subColor
For iSeg = 1 To nSeg
color1 = seg[iSeg]["color"]
Color_Sub()
GraphicsWindow.BrushColor = color
GraphicsWindow.FillRectangle(seg[iSeg]["x"], seg[iSeg]["y"], seg[iSeg]["width"], 1)
EndFor
EndSub

Sub Color_Sub
' param color1, color2 - for color subtraction
' return color - result
color = color1
Color_RGBToValues()
rgb1 = rgb
color = color2
Color_RGBToValues()
rgb2 = rgb
For i = 1 To 3
rgb[i] = Math.Max(rgb1[i] - (255 - rgb2[i]), 0)
EndFor
color = GraphicsWindow.GetColorFromRGB(rgb[1], rgb[2], rgb[3])
EndSub

Sub Color_RGBToValues
' param color - "#rrggbb"
' return rgb[] - 0..255 for each red, green, and blue
hex = Text.GetSubText(color, 2, 2)
Math_Hex2Dec()
rgb[1] = dec
hex = Text.GetSubText(color, 4, 2)
Math_Hex2Dec()
rgb[2] = dec
hex = Text.GetSubText(color, 6, 2)
Math_Hex2Dec()
rgb[3] = dec
EndSub

Sub Math_Hex2Dec
' Math | Convert hexadecimal to decimal
' param hex - hexadecimal
' return dec - decimal
dec = 0
len = Text.GetLength(hex)
For ptr = 1 To len
dec = dec * 16 + Text.GetIndexOf("123456789ABCDEF", Text.GetSubText(hex, ptr, 1))
EndFor
EndSub