Skip to content

Commit

Permalink
Merge pull request #582 from QB64-Phoenix-Edition/clamp-and-hsb-colors
Browse files Browse the repository at this point in the history
Clamp and hsb colors
  • Loading branch information
RhoSigma-QB64 authored Dec 1, 2024
2 parents a4e6c68 + 7ee7930 commit eeb277e
Show file tree
Hide file tree
Showing 5 changed files with 216 additions and 17 deletions.
4 changes: 2 additions & 2 deletions internal/support/converter/AddPREFIX.bas
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ SUB add_prefix
END SUB

SUB maybe_add_prefix
IF noprefix_detected AND token.t = TOK_WORD AND ASC(token.uc) <> ASC("_") _ANDALSO is_underscored(token.c) THEN add_prefix
IF noprefix_detected AND token.t = TOK_WORD AND ASC(token.uc) <> ASC("_") _ANDALSO is_underscored THEN add_prefix
END SUB

FUNCTION line_end
Expand All @@ -556,7 +556,7 @@ FUNCTION line_end
END SELECT
END FUNCTION

FUNCTION is_underscored (s$)
FUNCTION is_underscored
DIM i
FOR i = 1 TO UBOUND(prefix_keywords$)
IF token.uc = prefix_keywords$(i) THEN
Expand Down
165 changes: 160 additions & 5 deletions internal/support/include/afterlastline.bm
Original file line number Diff line number Diff line change
Expand Up @@ -56,17 +56,105 @@ $CHECKING:OFF
'_MIN() returns the lesser of both given values (returns value1 if equal).
'----------
FUNCTION _IKW_Min## (_value1##, _value2##)
IF _value1## <= _value2## THEN _MIN = _value1## ELSE _MIN = _value2##
_MIN = _IIF(_value1## <= _value2##, _value1##, _value2##)
END FUNCTION

'_MAX() returns the greater of both given values (returns value1 if equal).
'----------
FUNCTION _IKW_Max## (_value1##, _value2##)
IF _value1## >= _value2## THEN _MAX = _value1## ELSE _MAX = _value2##
_MAX = _IIF(_value1## >= _value2##, _value1##, _value2##)
END FUNCTION

'_EncodeURL$() returns the encoded version of the given plain text URL for
' use with the _OPENCLIENT("HTTP:url") syntax.
'_CLAMP() returns the given value or the min/max, if the value is lesser or
' greater than that respectively.
'----------
FUNCTION _IKW_Clamp## (_value##, _minVal##, _maxVal##)
DIM _realMin##, _realMax##
_realMin## = _MIN(_minVal##, _maxVal##)
_realMax## = _MAX(_minVal##, _maxVal##)
_CLAMP = _IIF(_value## < _realMin##, _realMin##, _IIF(_value## > _realMax##, _realMax##, _value##))
END FUNCTION

'_HSB32() returns the 32-bit ARGB color value build from the given HSB values,
' always with full alpha (opaque colors).
'---------- [0,360] [0,100] [0,100]
FUNCTION _IKW_HSB32~& (_hue#, _saturation#, _brightness#)
'--- option _explicit requirements ---
DIM _hu#, _sa#, _br#, _re#, _gr#, _bl#
'--- prepare values for conversion ---
_hu# = _CLAMP(_hue#, 0, 360)
_sa# = _CLAMP(_saturation#, 0, 100) / 100
_br# = _CLAMP(_brightness#, 0, 100) / 100
'--- convert colorspace ---
_HSBtoRGB _hu#, _sa#, _br#, _re#, _gr#, _bl#
'--- build result ---
_HSB32 = _RGB32(CINT(_re# * 255), CINT(_gr# * 255), CINT(_bl# * 255))
END FUNCTION

'_HSBA32() returns the 32-bit ARGB color value build from the given HSB values,
' using 0-100% alpha as given.
'---------- [0,360] [0,100] [0,100] [0,100]
FUNCTION _IKW_HSBA32~& (_hue#, _saturation#, _brightness#, _alfa#)
'--- option _explicit requirements ---
DIM _hu#, _sa#, _br#, _al#, _re#, _gr#, _bl#
'--- prepare values for conversion ---
_hu# = _CLAMP(_hue#, 0, 360)
_sa# = _CLAMP(_saturation#, 0, 100) / 100
_br# = _CLAMP(_brightness#, 0, 100) / 100
_al# = _CLAMP(_alfa#, 0, 100) / 100
'--- convert colorspace ---
_HSBtoRGB _hu#, _sa#, _br#, _re#, _gr#, _bl#
'--- build result ---
_HSBA32 = _RGBA32(CINT(_re# * 255), CINT(_gr# * 255), CINT(_bl# * 255), CINT(_al# * 255))
END FUNCTION

'_HUE32() returns the hue [0,360] of the given 32-bit ARGB color value.
'----------
FUNCTION _IKW_HUE32# (_argbColor~&)
'--- option _explicit requirements ---
DIM _re#, _gr#, _bl#, _hu#, _sa#, _br#
'--- prepare values for conversion ---
_re# = _RED32(_argbColor~&) / 255
_gr# = _GREEN32(_argbColor~&) / 255
_bl# = _BLUE32(_argbColor~&) / 255
'--- convert colorspace ---
_RGBtoHSB _re#, _gr#, _bl#, _hu#, _sa#, _br#
'--- build result ---
_HUE32 = _hu#
END FUNCTION

'_SATURATION32() returns the saturation [0,100] of the given 32-bit ARGB color value.
'----------
FUNCTION _IKW_SATURATION32# (_argbColor~&)
'--- option _explicit requirements ---
DIM _re#, _gr#, _bl#, _hu#, _sa#, _br#
'--- prepare values for conversion ---
_re# = _RED32(_argbColor~&) / 255
_gr# = _GREEN32(_argbColor~&) / 255
_bl# = _BLUE32(_argbColor~&) / 255
'--- convert colorspace ---
_RGBtoHSB _re#, _gr#, _bl#, _hu#, _sa#, _br#
'--- build result ---
_SATURATION32 = _sa# * 100
END FUNCTION

'_BRIGHTNESS32() returns the brightness [0,100] of the given 32-bit ARGB color value.
'----------
FUNCTION _IKW_BRIGHTNESS32# (_argbColor~&)
'--- option _explicit requirements ---
DIM _re#, _gr#, _bl#, _hu#, _sa#, _br#
'--- prepare values for conversion ---
_re# = _RED32(_argbColor~&) / 255
_gr# = _GREEN32(_argbColor~&) / 255
_bl# = _BLUE32(_argbColor~&) / 255
'--- convert colorspace ---
_RGBtoHSB _re#, _gr#, _bl#, _hu#, _sa#, _br#
'--- build result ---
_BRIGHTNESS32 = _br# * 100
END FUNCTION

'_EncodeURL$() returns the percent encoded version of the given plain text
' URL for use with the _OPENCLIENT("HTTP:url") syntax.
'----------
FUNCTION _IKW_EncodeURL$ (_url$)
'24 OCT 2024: First implementation based on the informations found on the website;
Expand Down Expand Up @@ -134,9 +222,76 @@ END FUNCTION
' rule #2 its names must begin with an underscore.
'==========================================================================

'_HSBtoRGB() converts colors from the HSB into the RGB colorspace. Note that
' HSB (B=Brightness) is also known as HSV (V=Value) and sometimes called
' HSI (I=Intensity), but that's just different names for the same thing.
' However, this SUB is not suitable for the HSL (L=Lightness) colorspace.
'----------
' IN: hu# = [0,360], sa# = [0,1], br# = [0,1]
'OUT: re#, gr#, bl# values in range [0,1] (through arguments)
'----------
SUB _HSBtoRGB (_hu#, _sa#, _br#, _re#, _gr#, _bl#)
'--- option _explicit requirements ---
DIM _hi%, _hf#, _pv#, _qv#, _tv#
'--- compute RGB ---
IF _sa# = 0 THEN
_re# = _br#: _gr# = _br#: _bl# = _br# 'no saturation = grayscale
ELSE
_hu# = _hu# / 60 ' 'to sixtant [0,5]
IF _hu# >= 6 THEN _hu# = _hu# - 6
_hi% = INT(_hu#): _hf# = _hu# - _hi% 'int/frac parts of hue
_pv# = _br# * (1 - _sa#)
_qv# = _br# * (1 - (_sa# * _hf#))
_tv# = _br# * (1 - (_sa# * (1 - _hf#)))
SELECT CASE _hi%
CASE 0: _re# = _br#: _gr# = _tv#: _bl# = _pv# ' 0- 60 = Red->Yellow
CASE 1: _re# = _qv#: _gr# = _br#: _bl# = _pv# ' 60-120 = Yellow->Green
CASE 2: _re# = _pv#: _gr# = _br#: _bl# = _tv# '120-180 = Green->Cyan
CASE 3: _re# = _pv#: _gr# = _qv#: _bl# = _br# '180-240 = Cyan->Blue
CASE 4: _re# = _tv#: _gr# = _pv#: _bl# = _br# '240-300 = Blue->Magenta
CASE 5: _re# = _br#: _gr# = _pv#: _bl# = _qv# '300-360 = Magenta->Red
END SELECT
END IF
END SUB

'_RGBtoHSB() converts colors from the RGB into the HSB colorspace. Note that
' HSB (B=Brightness) is also known as HSV (V=Value) and sometimes called
' HSI (I=Intensity), but that's just different names for the same thing.
' However, this SUB is not suitable for the HSL (L=Lightness) colorspace.
'----------
' IN: re#, gr#, bl# values in range [0,1]
'OUT: hu# = [0,360], sa# = [0,1], br# = [0,1] (through arguments)
'----------
SUB _RGBtoHSB (_re#, _gr#, _bl#, _hu#, _sa#, _br#)
'--- option _explicit requirements ---
DIM _mini#, _maxi#, _diff#
'--- find min/max and difference ---
_mini# = _MIN(_MIN(_re#, _gr#), _bl#)
_maxi# = _MAX(_MAX(_re#, _gr#), _bl#)
_diff# = _maxi# - _mini#
'--- brightness ---
_br# = _maxi#
'--- saturation (avoid division by zero) ---
IF _maxi# <> 0 THEN _sa# = _diff# / _maxi# ELSE _sa# = 0
'--- hue in degrees ---
IF _sa# <> 0 THEN
IF _re# = _maxi# THEN
_hu# = ((_gr# - _bl#) / _diff#) ' 'between Yellow & Magenta
IF _hu# < 0 THEN _hu# = _hu# + 6
ELSEIF _gr# = _maxi# THEN
_hu# = 2 + ((_bl# - _re#) / _diff#) 'between Cyan & Yellow
ELSE
_hu# = 4 + ((_re# - _gr#) / _diff#) 'between Magenta & Cyan
END IF
_hu# = _hu# * 60 'to degrees
ELSE
_hu# = 0 'technically there's no hue w/o saturation, commonly used is 0 (red)
END IF
END SUB

$IF _SOCKETS_ THEN
'_WhatIsMyIP$() is a helper function required by _CONNECTIONADDRESS$,
'but only required when network stuff is compiled in (_SOCKETS_).
' but only required when network stuff is compiled in (_SOCKETS_).
'----------
FUNCTION _WhatIsMyIP$
'01 NOV 2024: Make it part of this file, i.e. deprecating internal/c/myip.cpp;
Expand Down
8 changes: 4 additions & 4 deletions source/subs_functions/syntax_highlighter_list.bas
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ listOfKeywords$ = listOfKeywords$ +_
' [B] - Keywords alphabetical (1st line = QB64, 2nd line = QB4.5, 3rd line = OpenGL)
listOfKeywords$ = listOfKeywords$ +_
"_BEHIND@_BIN$@_BIT@_BLEND@_BLINK@_BLUE@_BLUE32@_BUTTON@_BUTTONCHANGE@_BYTE@" +_
"_BEHIND@_BIN$@_BIT@_BLEND@_BLINK@_BLUE@_BLUE32@_BRIGHTNESS32@_BUTTON@_BUTTONCHANGE@_BYTE@" +_
"BASE@BEEP@BINARY@BLOAD@BSAVE@BYVAL@" +_
"_GLBEGIN@_GLBINDTEXTURE@_GLBITMAP@_GLBLENDFUNC@"
' [C] - Keywords alphabetical (1st line = QB64, 2nd line = QB4.5, 3rd line = OpenGL)
listOfKeywords$ = listOfKeywords$ +_
"_CAPSLOCK@_CAST@_CEIL@_CINP@_CLEAR@_CLEARCOLOR@_CLIP@_CLIPBOARD$@_CLIPBOARDIMAGE@_CLOCKWISE@_COLORCHOOSERDIALOG@_COMMANDCOUNT@_CONNECTED@_CONNECTIONADDRESS@_CONNECTIONADDRESS$@_CONSOLE@_CONSOLECURSOR@_CONSOLEFONT@_CONSOLEINPUT@_CONSOLETITLE@_CONTINUE@_CONTROLCHR@_COPYIMAGE@_COPYPALETTE@_COSH@_COT@_COTH@_CRC32@_CSC@_CSCH@_CV@_CWD$@" +_
"_CAPSLOCK@_CAST@_CEIL@_CINP@_CLAMP@_CLEAR@_CLEARCOLOR@_CLIP@_CLIPBOARD$@_CLIPBOARDIMAGE@_CLOCKWISE@_COLORCHOOSERDIALOG@_COMMANDCOUNT@_CONNECTED@_CONNECTIONADDRESS@_CONNECTIONADDRESS$@_CONSOLE@_CONSOLECURSOR@_CONSOLEFONT@_CONSOLEINPUT@_CONSOLETITLE@_CONTINUE@_CONTROLCHR@_COPYIMAGE@_COPYPALETTE@_COSH@_COT@_COTH@_CRC32@_CSC@_CSCH@_CV@_CWD$@" +_
"CALL@CALLS@CASE@CDBL@CDECL@CHAIN@CHDIR@CHR$@CINT@CIRCLE@CLEAR@CLNG@CLOSE@CLS@COLOR@COM@COMMAND$@COMMON@CONSOLE@CONST@COS@CSNG@CSRLIN@CUSTOMTYPE@CVD@CVDMBF@CVI@CVL@CVS@CVSMBF@" +_
"_GLCALLLIST@_GLCALLLISTS@_GLCLEAR@_GLCLEARACCUM@_GLCLEARCOLOR@_GLCLEARDEPTH@_GLCLEARINDEX@_GLCLEARSTENCIL@_GLCLIPPLANE@_GLCOLOR3B@_GLCOLOR3BV@_GLCOLOR3D@_GLCOLOR3DV@_GLCOLOR3F@_GLCOLOR3FV@_GLCOLOR3I@_GLCOLOR3IV@_GLCOLOR3S@_GLCOLOR3SV@_GLCOLOR3UB@_GLCOLOR3UBV@_GLCOLOR3UI@_GLCOLOR3UIV@_GLCOLOR3US@_GLCOLOR3USV@_GLCOLOR4B@_GLCOLOR4BV@_GLCOLOR4D@_GLCOLOR4DV@_GLCOLOR4F@_GLCOLOR4FV@_GLCOLOR4I@_GLCOLOR4IV@_GLCOLOR4S@_GLCOLOR4SV@_GLCOLOR4UB@_GLCOLOR4UBV@_GLCOLOR4UI@_GLCOLOR4UIV@_GLCOLOR4US@_GLCOLOR4USV@_GLCOLORMASK@_GLCOLORMATERIAL@_GLCOLORPOINTER@_GLCOPYPIXELS@_GLCOPYTEXIMAGE1D@_GLCOPYTEXIMAGE2D@_GLCOPYTEXSUBIMAGE1D@_GLCOPYTEXSUBIMAGE2D@_GLCULLFACE@"
Expand Down Expand Up @@ -50,7 +50,7 @@ listOfKeywords$ = listOfKeywords$ +_
' [H] - Keywords alphabetical (1st line = QB64, 2nd line = QB4.5, 3rd line = OpenGL)
listOfKeywords$ = listOfKeywords$ +_
"_HARDWARE@_HARDWARE1@_HEIGHT@_HIDE@_HYPOT@" +_
"_HARDWARE@_HARDWARE1@_HEIGHT@_HIDE@_HSB32@_HSBA32@_HUE32@_HYPOT@" +_
"HEX$@" +_
"_GLHINT@"
Expand Down Expand Up @@ -116,7 +116,7 @@ listOfKeywords$ = listOfKeywords$ +_
' [S] - Keywords alphabetical (1st line = QB64, 2nd line = QB4.5, 3rd line = OpenGL)
listOfKeywords$ = listOfKeywords$ +_
"_SAVEFILEDIALOG$@_SAVEIMAGE@_SCALEDHEIGHT@_SCALEDWIDTH@_SCREENCLICK@_SCREENEXISTS@_SCREENHIDE@_SCREENICON@_SCREENIMAGE@_SCREENMOVE@_SCREENPRINT@_SCREENSHOW@_SCREENX@_SCREENY@_SCROLLLOCK@_SEAMLESS@_SEC@_SECH@_SELECTFOLDERDIALOG$@_SETALPHA@_SETBIT@_SHELLHIDE@_SHL@_SHOW@_SHR@_SINH@_SMOOTH@_SMOOTHSHRUNK@_SMOOTHSTRETCHED@_SNDBAL@_SNDCLOSE@_SNDCOPY@_SNDGETPOS@_SNDLEN@_SNDLIMIT@_SNDLOOP@_SNDNEW@_SNDOPEN@_SNDOPENRAW@_SNDPAUSE@_SNDPAUSED@_SNDPLAY@_SNDPLAYCOPY@_SNDPLAYFILE@_SNDPLAYING@_SNDRATE@_SNDRAW@_SNDRAWBATCH@_SNDRAWDONE@_SNDRAWLEN@_SNDSETPOS@_SNDSTOP@_SNDVOL@_SOFTWARE@_SOURCE@_SQUAREPIXELS@_STARTDIR$@_STATUSCODE@_STRCMP@_STRETCH@_STRICMP@" +_
"_SATURATION32@_SAVEFILEDIALOG$@_SAVEIMAGE@_SCALEDHEIGHT@_SCALEDWIDTH@_SCREENCLICK@_SCREENEXISTS@_SCREENHIDE@_SCREENICON@_SCREENIMAGE@_SCREENMOVE@_SCREENPRINT@_SCREENSHOW@_SCREENX@_SCREENY@_SCROLLLOCK@_SEAMLESS@_SEC@_SECH@_SELECTFOLDERDIALOG$@_SETALPHA@_SETBIT@_SHELLHIDE@_SHL@_SHOW@_SHR@_SINH@_SMOOTH@_SMOOTHSHRUNK@_SMOOTHSTRETCHED@_SNDBAL@_SNDCLOSE@_SNDCOPY@_SNDGETPOS@_SNDLEN@_SNDLIMIT@_SNDLOOP@_SNDNEW@_SNDOPEN@_SNDOPENRAW@_SNDPAUSE@_SNDPAUSED@_SNDPLAY@_SNDPLAYCOPY@_SNDPLAYFILE@_SNDPLAYING@_SNDRATE@_SNDRAW@_SNDRAWBATCH@_SNDRAWDONE@_SNDRAWLEN@_SNDSETPOS@_SNDSTOP@_SNDVOL@_SOFTWARE@_SOURCE@_SQUAREPIXELS@_STARTDIR$@_STATUSCODE@_STRCMP@_STRETCH@_STRICMP@" +_
"SADD@SCREEN@SEEK@SEG@SELECT@SETMEM@SGN@SHARED@SHELL@SIGNAL@SIN@SINGLE@SLEEP@SMOOTH@SOUND@SPACE$@SPC@SQR@STATIC@STEP@STICK@STOP@STR$@STRETCH@STRIG@STRING@STRING$@SUB@SWAP@SYSTEM@" +_
"_GLSCALED@_GLSCALEF@_GLSCISSOR@_GLSELECTBUFFER@_GLSHADEMODEL@_GLSTENCILFUNC@_GLSTENCILMASK@_GLSTENCILOP@"
Expand Down
37 changes: 31 additions & 6 deletions tests/compile_tests/colors/test.bas
Original file line number Diff line number Diff line change
@@ -1,8 +1,33 @@
$Console:Only
$CONSOLE:ONLY

Print "Grey, max alpha: "; Hex$(_RGB32(&H7F))
Print "Grey, half alpha: "; Hex$(_RGB32(&H7F, &H7F))
Print "Grey, max alpha: "; Hex$(_RGB32(&H7F, &H7F, &H7F))
Print "Grey, half alpha: "; Hex$(_RGB32(&H7F, &H7F, &H7F, &H7F))
PRINT "RGB functions forward"
PRINT "Grey, max alpha: "; HEX$(_RGB32(127))
PRINT "Grey, half alpha: "; HEX$(_RGB32(127, 127))
PRINT "Grey, max alpha: "; HEX$(_RGB32(127, 127, 127))
PRINT "Grey, half alpha: "; HEX$(_RGB32(127, 127, 127, 127))

c~& = _RGBA32(80, 128, 160, 32)
PRINT
PRINT "RGB functions backward _RGBA32(80, 128, 160, 32)"
PRINT "Red..:"; _RED32(c~&)
PRINT "Green:"; _GREEN32(c~&)
PRINT "Blue.:"; _BLUE32(c~&)
PRINT "Alpha:"; _ALPHA32(c~&)

PRINT
PRINT "HSB functions forward"
PRINT "Red, max alpha: "; HEX$(_HSB32(0, 100, 100))
PRINT "Red, half alpha: "; HEX$(_HSBA32(0, 100, 100, 50))
PRINT "Midgreen, max alpha: "; HEX$(_HSB32(120, 75, 75))
PRINT "Midgreen, 3/4 alpha: "; HEX$(_HSBA32(120, 75, 75, 75))

c~& = _HSBA32(90, 75, 65, 55)
PRINT
PRINT "HSB functions backward _HSBA32(90, 75, 65, 55)"
PRINT "Hue.......:"; CINT(_HUE32(c~&))
PRINT "Saturation:"; CINT(_SATURATION32(c~&))
PRINT "Brightness:"; CINT(_BRIGHTNESS32(c~&))
PRINT "Alpha.....:"; CINT(_ALPHA32(c~&) / 255 * 100)

SYSTEM

System
19 changes: 19 additions & 0 deletions tests/compile_tests/colors/test.output
Original file line number Diff line number Diff line change
@@ -1,4 +1,23 @@
RGB functions forward
Grey, max alpha: FF7F7F7F
Grey, half alpha: 7F7F7F7F
Grey, max alpha: FF7F7F7F
Grey, half alpha: 7F7F7F7F

RGB functions backward _RGBA32(80, 128, 160, 32)
Red..: 80
Green: 128
Blue.: 160
Alpha: 32

HSB functions forward
Red, max alpha: FFFF0000
Red, half alpha: 80FF0000
Midgreen, max alpha: FF30BF30
Midgreen, 3/4 alpha: BF30BF30

HSB functions backward _HSBA32(90, 75, 65, 55)
Hue.......: 90
Saturation: 75
Brightness: 65
Alpha.....: 55

0 comments on commit eeb277e

Please sign in to comment.