module Graphics.Rendering.Rect.Border(renderBorder, Border(..), BorderStyle(..), topColour, rightColour, bottomColour, leftColour) where import Graphics.Rendering.Rect.CSS.Border import Graphics.Rendering.Rect.Types import qualified Data.ByteString.Char8 as B8 import Control.Monad.IO.Class (MonadIO(..)) import Linear (M44) borderFragmentShader :: B8.ByteString borderFragmentShader = B8.pack $ unlines [ "#version 330 core", "uniform float widths[4];", "uniform vec4 colours[4];", "uniform int styles[5];", "uniform vec2 boxSize;", "in vec2 coord;", "out vec4 fcolour;", "", "const int TOP = 0;", "const int RIGHT = 1;", "const int BOTTOM = 2;", "const int LEFT = 3;", "const int NONE = 4;", "", "const int NOBORDER = 0;", "const int SOLID = 1;", "const int DASHED = 2;", "const int DOTTED = 3;", "const int DOUBLE = 4;", "const int GROOVE = 5;", "const int RIDGE = 6;", "const int INSET = 7;", "const int OUTSET = 8;", "", "bool inTrap(float x, float y, float width, int height, int left, int right) {", " float a = y/widths[height];", " return a*widths[left] <= x && x <= width - widths[right]*a;", "}", "", "void main() {", " int side = NONE;", " if (coord.y < abs(widths[TOP]) &&", " inTrap(coord.x, coord.y, boxSize.x, TOP, LEFT, RIGHT))", " side = TOP;", " else if (coord.x < abs(widths[LEFT]) &&", " inTrap(coord.y, coord.x, boxSize.y, LEFT, TOP, BOTTOM))", " side = LEFT;", " else if (boxSize.x - coord.x < abs(widths[RIGHT]) &&", " inTrap(coord.y, boxSize.x-coord.x, boxSize.y, RIGHT,TOP,BOTTOM))", " side = RIGHT;", " else if (boxSize.y - coord.y < abs(widths[BOTTOM])) side = BOTTOM;", "", " vec2 pos = coord;", " if (side == RIGHT || side == BOTTOM) pos = boxSize - coord;", " if (side == TOP || side == BOTTOM) pos = pos.xy;", "", " if (styles[side] == SOLID) fcolour = colours[side];", " else fcolour = vec4(0.0);", "}" ] renderBorder :: (MonadIO m, MonadIO n) => n (Border -> Rects -> M44 Float -> m ()) renderBorder = do inner <- renderRectWith borderFragmentShader [ "widths[0]", "widths[1]", "widths[2]", "widths[3]", "colours[0]", "colours[1]", "colours[2]", "colours[3]", "styles[0]", "styles[1]", "styles[2]", "styles[3]", "styles[4]"] return $ \self rects -> let (b, p) = (borderBox rects, paddingBox rects) in inner [] [ u $ top p - top b, u $ right b - right p, u $ bottom b - bottom p, u $ left p - left b, c $ topColour self, c $ rightColour self, c $ bottomColour self, c $ leftColour self, u $ fromEnum $ topStyle self, u $ fromEnum $ rightStyle self, u $ fromEnum $ bottomStyle self, u $ fromEnum $ leftStyle self, u (0 :: Int) ] borderBox borderBox rects