~alcinnz/Mondrian

e816039387124999a1dd08a4de554e0f47864c0a — Adrian Cochrane 1 year, 6 months ago c4d7272
Add support for colour stops, equally spaced.

10 stops should be generous!
M lib/Graphics/Rendering/Rect.hs => lib/Graphics/Rendering/Rect.hs +1 -1
@@ 35,7 35,7 @@ styleResolveImages atlas self =
  where
    atlasLookup' None = None
    atlasLookup' (Img path) = Img $ atlasLookup path atlas
    atlasLookup' (Linear a b c) = Linear a b c
    atlasLookup' (Linear a b) = Linear a b

atlasFromStyles :: MonadIO m =>
        (Text -> IO DynamicImage) -> [RectStyle Text] -> m Atlas

M lib/Graphics/Rendering/Rect/Backgrounds.hs => lib/Graphics/Rendering/Rect/Backgrounds.hs +7 -6
@@ 32,15 32,16 @@ linearFragmentShader = B8.pack $ unlines [
    "in vec2 coord;",
    "out vec4 fcolour;",
    "uniform vec2 size;",
    "uniform vec4 start;",
    "uniform vec4 end;",
    "uniform vec4 stops[10];",
    "uniform int nStops;",
    "uniform float angle;",
    "void main() {",
    "   vec2 pos = coord/size;", -- Range 0..1
    "   pos -= 0.5; pos *= 2;", -- Range -1..1
    "   float a = pos.x*sin(angle) + pos.y*-cos(angle);", -- Range -1..1
    "   a /= 2; a += 0.5;", -- Range 0..1
    "   fcolour = mix(start, end, a);",
    "   a *= float(min(nStops, 10) - 1);", -- Range 0..(nStops-1)
    "   fcolour = mix(stops[int(floor(a))], stops[int(ceil(a))], fract(a));",
    "}"
  ]



@@ 49,7 50,7 @@ renderBackgrounds :: (MonadIO m, MonadIO n) =>
renderBackgrounds = do
    base <- renderRectWith baseFragmentShader ["colour"]
    layer <- renderRectWith imageFragmentShader ["size"]
    linear <- renderRectWith linearFragmentShader ["size", "start", "end", "angle"]
    linear <- renderRectWith linearFragmentShader ["size","stops","nStops","angle"]
    return $ \self a b -> do
        base [] [c $ background self] (headDef borderBox $ clip self) a b
        let layers = image self `zip` (clip self ++ repeat borderBox)


@@ 59,8 60,8 @@ renderBackgrounds = do
            Img img0 -> layer [img0] [
                    u $ v2 $ resolveSize (size $ clip0 a) (texSize img0) size0
                ] clip0 a b
            Linear angle start end -> linear [] [
                    u $ v2 $ size $ clip0 a, c start, c end, u angle
            Linear angle stops -> linear [] [
                    u $ v2 $ size $ clip0 a, cs 10 stops, u $ length stops, u angle
                ] clip0 a b
        return ()


M lib/Graphics/Rendering/Rect/CSS/Backgrounds.hs => lib/Graphics/Rendering/Rect/CSS/Backgrounds.hs +9 -9
@@ 24,7 24,7 @@ data Backgrounds img = Backgrounds {

type C = AlphaColour Float

data Pattern img = None | Img img | Linear Float C C deriving (Eq, Show, Read)
data Pattern img = None | Img img | Linear Float [C] deriving (Eq, Show, Read)

-- We need to resolve images before we can compute the actual lengths!
data Resize = Cover | Contain | Size Length Length deriving (Eq, Show, Read)


@@ 56,16 56,16 @@ instance PropertyParser (Backgrounds Text) where
        inner [Url ret] = Just $ Img ret
        inner [Function "url", String ret, RightParen] = Just $ Img ret
        inner (Function "linear-gradient":toks)
            | Just [s, e] <- colourStops (Comma:toks) = Just $ Linear pi s e
            | Just cs@(_:_:_) <- colourStops (Comma:toks) = Just $ Linear pi cs
        inner (Function "linear-gradient":Dimension _ x unit:toks)
            | Just rad <- lookup unit [("deg", pi/180), ("grad", pi/200),
            | Just s <- lookup unit [("deg", pi/180), ("grad", pi/200),
                    ("rad", 1), ("turn", 2*pi)],
                Just [s, e] <- colourStops toks = Just $ Linear (f x*rad) s e
                Just cs@(_:_:_) <- colourStops toks = Just $ Linear (f x*s) cs
        inner (Function "linear-gradient":Ident "to":Ident a:Ident b:toks)
            | Just angle <- corner a b, Just [s, e] <- colourStops toks =
                Just $ Linear angle s e
            | Just angle <- corner b a, Just [s, e] <- colourStops toks =
                Just $ Linear angle s e
            | Just angle <- corner a b, Just stops@(_:_:_) <- colourStops toks =
                Just $ Linear angle stops
            | Just angle <- corner b a, Just stops@(_:_:_) <- colourStops toks =
                Just $ Linear angle stops
          where
            corner "top" "right" = Just $ 0.25*pi
            corner "bottom" "right" = Just $ 0.75*pi


@@ 75,7 75,7 @@ instance PropertyParser (Backgrounds Text) where
        inner (Function "linear-gradient":Ident "to":Ident side:toks)
            | Just angle <- lookup side [
                ("top", 0), ("right", pi/2), ("bottom", pi), ("left", pi*1.5)],
                Just [s, e] <- colourStops toks = Just $ Linear angle s e
                Just cs@(_:_:_) <- colourStops toks = Just $ Linear angle cs
        inner _ = Nothing
        colourStops [RightParen] = Just []
        colourStops (Comma:toks)

M lib/Graphics/Rendering/Rect/Types.hs => lib/Graphics/Rendering/Rect/Types.hs +12 -3
@@ 2,7 2,7 @@
-- So getters can implement typeclasses
{-# LANGUAGE TypeSynonymInstances, FlexibleInstances #-}
module Graphics.Rendering.Rect.Types(Rect(..), size, Rects(..), BoxSelector,
        Uniform, u, c, renderRectWith, liftGL) where
        Uniform, u, c, cs, renderRectWith, liftGL) where

import Linear (M44, V2(..), V4(..))
import qualified Data.ByteString.Char8 as B8


@@ 12,7 12,8 @@ import qualified Data.Vector.Unboxed as UV
import Typograffiti.GL
import Graphics.GL.Core32
import Graphics.GL.Types
import Foreign.Marshal.Array (withArray)
import Foreign.Marshal.Array (withArray, withArrayLen)
import Foreign.Ptr (castPtr)

import Control.Monad.IO.Class (MonadIO(..))
import Control.Monad (forM)


@@ 75,11 76,19 @@ u :: (MonadIO m, UniformValue a) => a -> Uniform m
u val prog slot = liftIO $ updateUniform prog slot val

c :: MonadIO m => AlphaColour Float -> Uniform m
c rgba = u $ V4 r g b a
c rgba = u $ c' rgba
c' :: AlphaColour Float -> V4 Float
c' rgba = V4 r g b a
  where
    a = alphaChannel rgba
    -- Workaround for missing APIs in "colour" hackage.
    RGB r g b = toSRGB $ over rgba black
cs :: MonadIO m => Int -> [AlphaColour Float] -> Uniform m
cs mlen rgba prog slot = do
    let val = map c' $ take mlen rgba
    liftIO $ withArrayLen val $ \len ->
        glUniform4fv slot (toEnum len) . castPtr
    clearUniformUpdateError prog slot val

renderRectWith :: (MonadIO m, MonadIO n) => ByteString -> [String] ->
        n ([Texture] -> [Uniform m] -> (a -> Rect) -> a -> M44 Float -> m ())