From b691edeec1fcfa816ad5a632447fc2f5469a6588 Mon Sep 17 00:00:00 2001 From: Christian Walther Date: Wed, 20 Jul 2011 13:48:08 +0200 Subject: [PATCH] Higher-quality cursors with a shadow to make them visible on light backgrounds. Same look as in 760606d except for the linking book, which got a slight curvature on the pages (inspired by Deledrius' one, 99bda8c). The SVG is hand-tweaked to work around some differences in rendering between rsvg and Inkscape. I hope editing it in Inkscape again won't break the tweaks, check the diff closely if you do! Effects (blurred shadows) appear to be clipped to the SVG viewport by rsvg, which is why drawing the whole SVG shifted for the book cursors no longer works and we shift individual layers inside the SVG instead. --- .../Apps/plClient/external/Cursor_Base.svg | 1053 ++++++++++++----- .../Apps/plClient/external/render_svg.py | 58 +- 2 files changed, 802 insertions(+), 309 deletions(-) diff --git a/Sources/Plasma/Apps/plClient/external/Cursor_Base.svg b/Sources/Plasma/Apps/plClient/external/Cursor_Base.svg index 737abfec..88a2deae 100644 --- a/Sources/Plasma/Apps/plClient/external/Cursor_Base.svg +++ b/Sources/Plasma/Apps/plClient/external/Cursor_Base.svg @@ -7,19 +7,83 @@ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" + xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" - width="634.85712" - height="634.85712" + width="48" + height="48" id="svg2" version="1.1" - inkscape:version="0.48.0 r9654" - inkscape:export-xdpi="11.1" - inkscape:export-ydpi="11.1" - sodipodi:docname="Cursor_Base.svg" - style="display:inline"> + inkscape:version="0.48.1 r9760" + sodipodi:docname="making of cursors.svg" + inkscape:export-xdpi="360" + inkscape:export-ydpi="360"> + id="defs4"> + + + + + + + + + + + + + - - - - - - - - - - - + inkscape:window-width="1541" + inkscape:window-height="889" + inkscape:window-x="0" + inkscape:window-y="0" + inkscape:window-maximized="0" + inkscape:object-nodes="true" + inkscape:snap-grids="true"> + + + @@ -104,280 +151,714 @@ - + id="layer1" + style="display:none" + sodipodi:insensitive="true"> + - + id="layer5" + inkscape:label="poised orig out" + style="display:none" + sodipodi:insensitive="true"> + - + id="layer2" + inkscape:label="4wayclosed orig in" + style="display:none" + sodipodi:insensitive="true"> + - + inkscape:groupmode="layer" + id="layer6" + inkscape:label="4wayclosed orig out" + style="opacity:0.5;display:none" + sodipodi:insensitive="true"> + + id="layer18" + inkscape:label="shapes 1" + style="display:none"> + + + sodipodi:nodetypes="ccccccccccccccccccsscccccccccssccccccc" /> + id="layer19" + inkscape:label="shapes 2" + style="display:none"> + id="path6749" + d="m 27.7,24 c 0,2.378573 -1.321428,3.7 -3.7,3.7 -2.378573,0 -3.7,-1.321427 -3.7,-3.7 0,-2.378572 1.321427,-3.7 3.7,-3.7 2.378572,0 3.700001,1.321428 3.7,3.7 z" + style="fill-rule:evenodd;stroke:none;display:inline" /> + + + + + id="layer20" + inkscape:label="shapes 3" + style="display:none"> + transform="translate(0,-192)" + id="path6758" + d="m 14.5,205 -1.5,1.5 5.15625,5.15625 C 17.409919,212.77794 17,214.22611 17,216 c 0,1.77389 0.409919,3.22206 1.15625,4.34375 L 13,225.5 l 1.5,1.5 5.15625,-5.15625 C 20.777944,222.59008 22.226111,223 24,223 c 1.773889,0 3.222056,-0.40992 4.34375,-1.15625 L 33.5,227 35,225.5 29.84375,220.34375 C 30.590081,219.22206 31,217.77389 31,216 c 0,-1.77389 -0.409919,-3.22206 -1.15625,-4.34375 L 35,206.5 33.5,205 28.34375,210.15625 C 27.222055,209.40992 25.773889,209 24,209 c -1.773889,0 -3.222056,0.40992 -4.34375,1.15625 L 14.5,205 z m 9.5,6 c 1.128621,0 2.082846,0.23139 2.84375,0.65625 l -1,1 C 25.330626,212.42921 24.710234,212.3125 24,212.3125 c -0.710234,0 -1.330626,0.11671 -1.84375,0.34375 l -1,-1 C 21.917154,211.23139 22.871379,211 24,211 z m -4.34375,2.15625 1,1 c -0.227037,0.51312 -0.34375,1.13352 -0.34375,1.84375 0,0.71023 0.116713,1.33063 0.34375,1.84375 l -1,1 C 19.23139,218.08285 19,217.12862 19,216 c 0,-1.12862 0.23139,-2.08285 0.65625,-2.84375 z m 8.6875,0 C 28.76861,213.91715 29,214.87138 29,216 c 0,1.12862 -0.23139,2.08285 -0.65625,2.84375 l -1,-1 c 0.227038,-0.51312 0.34375,-1.13352 0.34375,-1.84375 0,-0.71023 -0.116712,-1.33063 -0.34375,-1.84375 l 1,-1 z m -6.1875,6.1875 c 0.513124,0.22704 1.133516,0.34375 1.84375,0.34375 0.710234,0 1.330626,-0.11671 1.84375,-0.34375 l 1,1 C 26.082847,220.76861 25.128621,221 24,221 c -1.128621,0 -2.082846,-0.23139 -2.84375,-0.65625 l 1,-1 z" + style="stroke:none;display:inline" /> - + id="circleOuterShadow" + inkscape:label="shadow outer circle" + style="display:inline"> + + + + + + + + - - - - + inkscape:label="shadow lower arrow translucent" + id="arrowTranslucentLowerShadow" + inkscape:groupmode="layer"> + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/Plasma/Apps/plClient/external/render_svg.py b/Sources/Plasma/Apps/plClient/external/render_svg.py index b8d103c5..e19e3585 100644 --- a/Sources/Plasma/Apps/plClient/external/render_svg.py +++ b/Sources/Plasma/Apps/plClient/external/render_svg.py @@ -20,30 +20,32 @@ cursorList = { "cursor_up": ["circleOuter"], "cursor_poised": ["circleOuter", "circleInnerOpen"], "cursor_clicked": ["circleOuter", "circleInnerClosed"], - "cursor_disabled": ["circleOuter", "cross"], + "cursor_disabled": ["cross"], - "cursor_open": ["circleOuter", "arrowGreyUpper", "arrowGreyLower"], - "cursor_grab": ["circleOuter", "circleInnerClosed", "arrowGreyUpper", "arrowGreyLower"], - "cursor_updown_open": ["circleOuter", "circleInnerClosed", "arrowGreyUpper", "arrowGreyLower"], - "cursor_updown_closed": ["circleOuter", "circleInnerClosed", "arrowWhiteUpper", "arrowWhiteLower"], + "cursor_open": ["circleOuter", "arrowTranslucentUpper", "arrowTranslucentLower"], + "cursor_grab": ["circleOuter", "circleInnerOpen", "arrowTranslucentUpper", "arrowTranslucentLower"], + "cursor_updown_open": ["circleOuter", "circleInnerOpen", "arrowTranslucentUpper", "arrowTranslucentLower"], + "cursor_updown_closed": ["circleOuter", "circleInnerClosed", "arrowOpaqueUpper", "arrowOpaqueLower"], - "cursor_leftright_open": ["circleOuter", "circleInnerClosed", "arrowGreyRight", "arrowGreyLeft"], - "cursor_leftright_closed": ["circleOuter", "circleInnerClosed", "arrowWhiteRight", "arrowWhiteLeft"], + "cursor_leftright_open": ["circleOuter", "circleInnerOpen", "arrowTranslucentLeft", "arrowTranslucentRight"], + "cursor_leftright_closed": ["circleOuter", "circleInnerClosed", "arrowOpaqueLeft", "arrowOpaqueRight"], - "cursor_4way_open": ["circleOuter", "circleInnerClosed", "arrowGreyUpper", "arrowGreyRight", "arrowGreyLower", "arrowGreyLeft"], - "cursor_4way_closed": ["circleOuter", "circleInnerClosed", "arrowWhiteUpper", "arrowWhiteRight", "arrowWhiteLower", "arrowWhiteLeft"], + "cursor_4way_open": ["circleOuter", "circleInnerOpen", "arrowTranslucentUpper", "arrowTranslucentRight", "arrowTranslucentLower", "arrowTranslucentLeft"], + "cursor_4way_closed": ["circleOuter", "circleInnerClosed", "arrowOpaqueUpper", "arrowOpaqueRight", "arrowOpaqueLower", "arrowOpaqueLeft"], - "cursor_upward": ["circleOuter", "arrowWhiteUpper"], - "cursor_right": ["circleOuter", "arrowWhiteRight"], - "cursor_down": ["circleOuter", "arrowWhiteLower"], - "cursor_left": ["circleOuter", "arrowWhiteLeft"], + "cursor_upward": ["circleOuter", "arrowOpaqueUpper"], + "cursor_right": ["circleOuter", "arrowOpaqueRight"], + "cursor_down": ["circleOuter", "arrowOpaqueLower"], + "cursor_left": ["circleOuter", "arrowOpaqueLeft"], "cursor_book": ["circleOuter", "book"], "cursor_book_poised": ["circleOuter", "circleInnerOpen", "book"], "cursor_book_clicked": ["circleOuter", "circleInnerClosed", "book"], } cursorOffsetList = { - "book": [8, 8] + "cursor_book": [7, 7], + "cursor_book_poised": [7, 7], + "cursor_book_clicked": [7, 7] } textList = { @@ -62,6 +64,15 @@ def enable_only_layers(layerlist, layers): layers[layer].setAttribute("style","") else: layers[layer].setAttribute("style","display:none") + # sanity check + for layer in layerlist: + if layer not in layers: + print("warning: unknown layer", layer) + +def shift_all_layers(layers, shiftx, shifty): + # note: this assumes that all layers start out with no transform of their own + for layer in layers: + layers[layer].setAttribute("transform", "translate(%g,%g)" % (shiftx, shifty)) def get_layers_from_svg(svgData): inkscapeNS = "http://www.inkscape.org/namespaces/inkscape" @@ -75,13 +86,13 @@ def get_layers_from_svg(svgData): return layers def render_cursors(inpath, outpath): - resSize = {"width":32, "height":32} + scalefactor = 1 with open(os.path.join(inpath,"Cursor_Base.svg"), "r") as svgFile: cursorSVG = parse(svgFile) layers = get_layers_from_svg(cursorSVG) - ratioW = resSize["width"] / float(cursorSVG.documentElement.getAttribute("width")) - ratioH = resSize["height"] / float(cursorSVG.documentElement.getAttribute("height")) - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, resSize["width"], resSize["height"]) + svgwidth = float(cursorSVG.documentElement.getAttribute("width")) + svgheight = float(cursorSVG.documentElement.getAttribute("height")) + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, int(math.ceil(scalefactor*svgwidth)), int(math.ceil(scalefactor*svgheight))) for cursor in cursorList: ctx = cairo.Context(surface) @@ -90,13 +101,14 @@ def render_cursors(inpath, outpath): ctx.paint() ctx.restore() - enable_only_layers(cursorList[cursor], layers) + enabledlayers = cursorList[cursor] + enabledlayers = enabledlayers + [l + "Shadow" for l in enabledlayers] + enable_only_layers(enabledlayers, layers) + + shift_all_layers(layers, *cursorOffsetList.get(cursor, [0, 0])) - for layerName in cursorOffsetList: - if layerName in cursorList[cursor]: - ctx.translate(*cursorOffsetList[layerName]) svg = rsvg.Handle(data=cursorSVG.toxml()) - ctx.scale(ratioW, ratioH) + ctx.scale(scalefactor, scalefactor) svg.render_cairo(ctx) surface.write_to_png(os.path.join(outpath, cursor + ".png"))