背景

一直想写个本地音乐播放器,类似 foobar2000AIMP

先取个名吧,来个脑洞词 poplayer (popular + player)

再设计个logo吧,决定用SVG手写

音乐符号的unicode码x266B 参考

也可以直接输入符号

上代码

logo.svg

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
     width="32" height="32">
  <defs>
    <linearGradient id="grad1" x1="0%" y1="100%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(115,70,200);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,50,100);stop-opacity:1" />
    </linearGradient>
  </defs>
  <circle cx="16" cy="16" r="16" fill="url(#grad1)" />
  <text fill="#000000" font-size="24" font-family="Arial, sans-serif" x="16" y="16"
        text-anchor="middle" dominant-baseline="central">&#x266B;</text>
</svg>

效果图如下

logo-poplayer.svg

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<svg xmlns="http://www.w3.org/2000/svg" version="1.1"
     width="120" height="32">
  <defs>
    <linearGradient id="grad1" x1="0%" y1="100%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(115,70,200);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,50,100);stop-opacity:1" />
    </linearGradient>
  </defs>
  <circle cx="16" cy="16" r="16" fill="url(#grad1)" />
  <text fill="#000000" font-size="24" font-family="Arial, sans-serif" x="16" y="16"
        text-anchor="middle" dominant-baseline="central">♫</text>
  <text fill="rgb(255,50,100)" font-size="20" font-family="Arial, sans-serif" x="32" y="16"
        font-weight="bold" dominant-baseline="central">Poplayer</text>
</svg>

效果图如下

Qt中加载SVG

加载到Qt中发现音乐符号和文字的位置不对,是<text>中的某些居中属性Qt没有正确识别? 经过一番搜索,发现SVG Tiny不是完整的SVG规范

参考如下:

Rendering SVG Files

SVG 1.2 Tiny

解决办法:

使用 inkscape<text>转换为<path>路径绘制

  • 打开svg文件

  • CTRL + A 选中所有对象

  • 路径 – 对象转路径

  • 导出 Plain svg

path/logo.svg

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   version="1.1"
   width="32"
   height="32"
   id="svg2"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:svg="http://www.w3.org/2000/svg">
  <defs
     id="defs2">
    <linearGradient
       id="grad1"
       x1="0"
       y1="32"
       x2="32"
       y2="0"
       gradientUnits="userSpaceOnUse">
      <stop
         offset="0%"
         style="stop-color:rgb(115,70,200);stop-opacity:1"
         id="stop1" />
      <stop
         offset="100%"
         style="stop-color:rgb(255,50,100);stop-opacity:1"
         id="stop2" />
    </linearGradient>
  </defs>
  <path
     id="circle2"
     style="fill:url(#grad1)"
     d="M 32,16 A 16,16 0 0 1 16,32 16,16 0 0 1 0,16 16,16 0 0 1 16,0 16,16 0 0 1 32,16 Z" />
  <path
     d="m 13.257813,7.7235751 9.328124,-2.90625 V 17.8017 q 0,1.453125 -0.375,2.191406 -0.363281,0.738282 -1.253906,1.21875 -0.878906,0.480469 -1.992187,0.480469 -1.277344,0 -2.039063,-0.726562 -0.761719,-0.738282 -0.761719,-1.898438 0,-1.171875 0.902344,-2.015625 0.902344,-0.855469 2.332031,-0.855469 0.46875,0 0.820313,0.08203 0.363281,0.08203 1.171875,0.421875 V 8.2157626 l -6.972656,2.1679684 v 9.796875 q 0,1.417969 -0.375,2.214844 -0.375,0.785156 -1.289063,1.253906 -0.914062,0.46875 -1.992187,0.46875 -1.277344,0 -2.027344,-0.726562 -0.7382813,-0.714844 -0.7382813,-1.875 0,-1.230469 0.8906251,-2.0625 0.890625,-0.84375 2.3320312,-0.84375 0.914063,0 2.039063,0.539062 z"
     id="text2"
     style="font-size:24px;font-family:Arial, sans-serif;dominant-baseline:central;text-anchor:middle"
     aria-label="♫" />
</svg>

path/logo-poplayer.svg

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
   version="1.1"
   width="116.73633"
   height="32"
   id="svg3"
   xmlns="http://www.w3.org/2000/svg"
   xmlns:svg="http://www.w3.org/2000/svg">
  <defs
     id="defs2">
    <linearGradient
       id="grad1"
       x1="0"
       y1="32"
       x2="32"
       y2="0"
       gradientUnits="userSpaceOnUse">
      <stop
         offset="0%"
         style="stop-color:rgb(115,70,200);stop-opacity:1"
         id="stop1" />
      <stop
         offset="100%"
         style="stop-color:rgb(255,50,100);stop-opacity:1"
         id="stop2" />
    </linearGradient>
  </defs>
  <path
     id="circle2"
     style="fill:url(#grad1)"
     d="M 32,16 A 16,16 0 0 1 16,32 16,16 0 0 1 0,16 16,16 0 0 1 16,0 16,16 0 0 1 32,16 Z" />
  <path
     d="m 13.257813,7.7235751 9.328124,-2.90625 V 17.8017 q 0,1.453125 -0.375,2.191406 -0.363281,0.738282 -1.253906,1.21875 -0.878906,0.480469 -1.992187,0.480469 -1.277344,0 -2.039063,-0.726562 -0.761719,-0.738282 -0.761719,-1.898438 0,-1.171875 0.902344,-2.015625 0.902344,-0.855469 2.332031,-0.855469 0.46875,0 0.820313,0.08203 0.363281,0.08203 1.171875,0.421875 V 8.2157626 l -6.972656,2.1679684 v 9.796875 q 0,1.417969 -0.375,2.214844 -0.375,0.785156 -1.289063,1.253906 -0.914062,0.46875 -1.992187,0.46875 -1.277344,0 -2.027344,-0.726562 -0.7382813,-0.714844 -0.7382813,-1.875 0,-1.230469 0.8906251,-2.0625 0.890625,-0.84375 2.3320312,-0.84375 0.914063,0 2.039063,0.539062 z"
     id="text2"
     style="font-size:24px;font-family:Arial, sans-serif;dominant-baseline:central;text-anchor:middle"
     aria-label="♫" />
  <path
     d="M 33.455078,21.515089 V 7.1986823 h 4.638672 q 2.636719,0 3.4375,0.2148438 1.230469,0.3222656 2.060547,1.40625 0.830078,1.0742187 0.830078,2.7832029 0,1.31836 -0.478516,2.216797 -0.478515,0.898438 -1.220703,1.416016 -0.732422,0.507812 -1.49414,0.673828 -1.035157,0.205078 -2.998047,0.205078 h -1.884766 v 5.400391 z M 36.345703,9.6205573 v 4.0624997 h 1.582031 q 1.708985,0 2.285157,-0.224609 0.576171,-0.224609 0.898437,-0.703125 0.332031,-0.478516 0.332031,-1.113281 0,-0.78125 -0.458984,-1.289063 -0.458984,-0.5078123 -1.162109,-0.6347654 -0.517579,-0.097656 -2.080079,-0.097656 z m 9.794922,6.5624997 q 0,-1.367187 0.673828,-2.646484 0.673828,-1.279297 1.904297,-1.953125 1.240234,-0.673828 2.763672,-0.673828 2.353515,0 3.857422,1.533203 1.503906,1.523437 1.503906,3.857422 0,2.353515 -1.523438,3.90625 -1.513671,1.542969 -3.818359,1.542969 -1.425781,0 -2.724609,-0.644532 -1.289063,-0.644531 -1.962891,-1.884765 -0.673828,-1.25 -0.673828,-3.03711 z m 2.8125,0.146485 q 0,1.542968 0.732422,2.363281 0.732422,0.820312 1.80664,0.820312 1.074219,0 1.796875,-0.820312 0.732422,-0.820313 0.732422,-2.382813 0,-1.523437 -0.732422,-2.34375 -0.722656,-0.820312 -1.796875,-0.820312 -1.074218,0 -1.80664,0.820312 -0.732422,0.820313 -0.732422,2.363282 z m 9.960937,-5.185547 h 2.558594 v 1.523437 q 0.498047,-0.78125 1.347656,-1.269531 0.84961,-0.488281 1.884766,-0.488281 1.806641,0 3.066406,1.416015 1.259766,1.416016 1.259766,3.945313 0,2.597656 -1.269531,4.042969 -1.269532,1.435547 -3.076172,1.435547 -0.859375,0 -1.5625,-0.341797 -0.69336,-0.341797 -1.464844,-1.171875 v 5.224609 h -2.744141 z m 2.714844,5.009765 q 0,1.748047 0.69336,2.587891 0.693359,0.830078 1.689453,0.830078 0.957031,0 1.591797,-0.761719 0.634765,-0.771484 0.634765,-2.519531 0,-1.630859 -0.654297,-2.421875 -0.654297,-0.791015 -1.621093,-0.791015 -1.00586,0 -1.669922,0.78125 -0.664063,0.771484 -0.664063,2.294921 z m 9.580078,5.361329 V 7.1986823 h 2.744141 V 21.515089 Z m 7.607422,-7.207032 -2.490234,-0.449218 q 0.419922,-1.503907 1.445312,-2.226563 1.025391,-0.722656 3.046875,-0.722656 1.835938,0 2.734375,0.439453 0.898438,0.429687 1.259766,1.103516 0.371094,0.664062 0.371094,2.451171 l -0.0293,3.203125 q 0,1.367188 0.126953,2.021485 0.136719,0.644531 0.498047,1.386719 H 83.064453 Q 82.957031,21.241651 82.800781,20.704542 82.732422,20.460401 82.703125,20.382276 82,21.06587 81.199219,21.407667 q -0.800782,0.341797 -1.708985,0.341797 -1.601562,0 -2.529297,-0.869141 -0.917968,-0.869141 -0.917968,-2.197266 0,-0.878906 0.419922,-1.5625 0.419921,-0.693359 1.171875,-1.054687 0.761718,-0.371094 2.1875,-0.644531 1.923828,-0.361329 2.666015,-0.673829 v -0.273437 q 0,-0.791016 -0.390625,-1.123047 -0.390625,-0.341797 -1.474609,-0.341797 -0.732422,0 -1.142578,0.292969 -0.410157,0.283203 -0.664063,1.005859 z m 3.671875,2.226563 q -0.527344,0.175781 -1.669922,0.419922 -1.142578,0.24414 -1.49414,0.478515 -0.53711,0.38086 -0.53711,0.966797 0,0.576172 0.429688,0.996094 0.429687,0.419922 1.09375,0.419922 0.742187,0 1.416015,-0.488281 0.498047,-0.371094 0.654297,-0.908204 0.107422,-0.351562 0.107422,-1.33789 z m 4.101563,-5.390625 h 2.919922 l 2.480468,7.363281 2.421875,-7.363281 h 2.841797 l -3.662109,9.980469 -0.654297,1.80664 q -0.361328,0.908203 -0.693359,1.386719 -0.322266,0.478516 -0.751954,0.771484 -0.419921,0.302735 -1.044921,0.46875 -0.615235,0.166016 -1.396485,0.166016 -0.791015,0 -1.552734,-0.166016 L 87.253906,23.40962 q 0.644531,0.126953 1.16211,0.126953 0.957031,0 1.416015,-0.566406 0.458985,-0.556641 0.703125,-1.425782 z m 18.427736,7.070312 2.73437,0.458985 q -0.52734,1.503906 -1.66992,2.294922 -1.13281,0.78125 -2.8418,0.78125 -2.70507,0 -4.003902,-1.767579 -1.025391,-1.416015 -1.025391,-3.574218 0,-2.578125 1.347657,-4.033203 1.347656,-1.464844 3.408206,-1.464844 2.31445,0 3.65234,1.533203 1.33789,1.523437 1.2793,4.677734 h -6.875 q 0.0293,1.220703 0.66406,1.904297 0.63477,0.673828 1.58203,0.673828 0.64453,0 1.08399,-0.351562 0.43945,-0.351563 0.66406,-1.132813 z m 0.15625,-2.773437 q -0.0293,-1.191406 -0.61524,-1.806641 -0.58593,-0.625 -1.42578,-0.625 -0.89843,0 -1.48437,0.654297 -0.58594,0.654297 -0.57617,1.777344 z m 7.58789,6.074219 h -2.74414 V 11.143995 h 2.54883 v 1.474609 q 0.65429,-1.044922 1.17187,-1.376953 0.52735,-0.332031 1.19141,-0.332031 0.9375,0 1.80664,0.517578 l -0.84961,2.392578 q -0.69336,-0.449219 -1.28906,-0.449219 -0.57618,0 -0.97657,0.322266 -0.40039,0.3125 -0.63476,1.142578 -0.22461,0.830078 -0.22461,3.476563 z"
     id="text3"
     style="font-weight:bold;font-size:20px;font-family:Arial, sans-serif;dominant-baseline:central;fill:#ff3264"
     aria-label="Poplayer" />
</svg>

SVG转换ICO

  • SVG –> PNG

打开 Inkscape

打开 logo.svg

建议导出以下像素

logo_16x16.png

logo_24x24.png

logo_32x32.png

logo_48x48.png

  • PNG –> ICO

一个ico文件可以包含多种尺寸,方法如下:

打开 GIMP

文件 – 作为图层打开

选中以上4个png文件

文件 – 导出为

选择文件类型,选择ico

导出 logo_48x48.ico

贝塞尔曲线

曾经在 stackoverflow 回答过的一个关于贝塞尔曲线的问题,纯数学计算,手写 <path> 路径

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 500">
    <text x="80" y="162">line1</text>
    <text x="80" y="108">line2</text>
    <text x="80" y="54">line3</text>
    <path id="line1_red" d="" fill="none" stroke="red" stroke-width="48" stroke-linecap="round" stroke-linejoin="round" />
    <path id="line2_red" d="" fill="none" stroke="red" stroke-width="48" stroke-linecap="round" stroke-linejoin="round" />
    <path id="line3_red" d="" fill="none" stroke="red" stroke-width="48" stroke-linecap="round" stroke-linejoin="round" />

    <path id="line1_blue" d="" fill="none" stroke="blue" stroke-width="48" stroke-linecap="round" stroke-linejoin="round" />
    <path id="line2_blue" d="" fill="none" stroke="blue" stroke-width="48" stroke-linecap="round" stroke-linejoin="round" />
    <path id="line3_blue" d="" fill="none" stroke="blue" stroke-width="48" stroke-linecap="round" stroke-linejoin="round" />
    
    <path id="line1_green" d="" fill="none" stroke="green" stroke-width="48" stroke-linecap="round" stroke-linejoin="round" />
    <path id="line2_green" d="" fill="none" stroke="green" stroke-width="48" stroke-linecap="round" stroke-linejoin="round" />
    <path id="line3_green" d="" fill="none" stroke="green" stroke-width="48" stroke-linecap="round" stroke-linejoin="round" />
</svg>

<script>
    let line1_red = {};
    let line1_blue = {};
    line1_red.begin = { x: 162, y: 162 };
    line1_blue.end = { x: 756, y: 432 };
    let space = 54;

    let leg1 = line1_blue.end.y - line1_red.begin.y;
    let line1_intersection = { x: line1_blue.end.x - leg1, y: line1_red.begin.y };

    let line_red_length = 260;  // closed interval [0, 324]
    let line_blue_length = 280;  // closed interval [0, 381.837661840736]

    line1_red.end = { x: line1_red.begin.x + line_red_length , y: line1_red.begin.y };

    let line2_red = {
        begin: { x: line1_red.begin.x, y: line1_red.begin.y - space },
        end: { x: line1_red.end.x, y: line1_red.begin.y - space  }
    };

    let line3_red = {
        begin: { x: line2_red.begin.x, y: line2_red.begin.y - space },
        end: { x: line2_red.end.x, y: line2_red.begin.y - space }
    };

    let offsetone = Math.sqrt((line_blue_length**2) / 2);
    line1_blue.begin = {
        x: line1_blue.end.x - offsetone,
        y: line1_blue.end.y - offsetone
    };

    let offsettwo = Math.sqrt((space**2) / 2);
    let line2_blue = {
        begin: { x: line1_blue.begin.x + offsettwo, y: line1_blue.begin.y - offsettwo },
        end: { x: line1_blue.end.x + offsettwo, y: line1_blue.end.y - offsettwo }
    };

    let line3_blue = {
        begin: { x: line2_blue.begin.x + offsettwo, y: line2_blue.begin.y - offsettwo },
        end: { x: line2_blue.end.x + offsettwo, y: line2_blue.end.y - offsettwo }
    };

    let leg2 = line2_blue.end.y - line2_red.begin.y
    let line2_intersection = { x: line2_blue.end.x - leg2, y: line2_red.begin.y };

    let leg3 = line3_blue.end.y - line3_red.begin.y
    let line3_intersection = { x: line3_blue.end.x - leg3, y: line3_red.begin.y };

    let line1_green_control = line1_intersection;
    let line2_green_control = line2_intersection;
    let line3_green_control = line3_intersection;

    let line1_green = {
        begin: { x: line1_red.end.x, y: line1_red.end.y },
        end: { x: line1_blue.begin.x, y: line1_blue.begin.y }
    };
    let line2_green = {
        begin: { x: line2_red.end.x, y: line2_red.end.y },
        end: { x: line2_blue.begin.x, y: line2_blue.begin.y }
    };
    let line3_green = {
        begin: { x: line3_red.end.x, y: line3_red.end.y },
        end: { x: line3_blue.begin.x, y: line3_blue.begin.y }
    };

    let line1_red_d = `M ${line1_red.begin.x} ${line1_red.begin.y} L ${line1_red.end.x} ${line1_red.end.y}`;
    let line2_red_d = `M ${line2_red.begin.x} ${line2_red.begin.y} L ${line2_red.end.x} ${line2_red.end.y}`;
    let line3_red_d = `M ${line3_red.begin.x} ${line3_red.begin.y} L ${line3_red.end.x} ${line3_red.end.y}`;
    document.getElementById("line1_red").setAttribute("d", line1_red_d);
    document.getElementById("line2_red").setAttribute("d", line2_red_d);
    document.getElementById("line3_red").setAttribute("d", line3_red_d);

    let line1_blue_d = `M ${line1_blue.begin.x} ${line1_blue.begin.y} L ${line1_blue.end.x} ${line1_blue.end.y}`;
    let line2_blue_d = `M ${line2_blue.begin.x} ${line2_blue.begin.y} L ${line2_blue.end.x} ${line2_blue.end.y}`;
    let line3_blue_d = `M ${line3_blue.begin.x} ${line3_blue.begin.y} L ${line3_blue.end.x} ${line3_blue.end.y}`;
    document.getElementById("line1_blue").setAttribute("d", line1_blue_d);
    document.getElementById("line2_blue").setAttribute("d", line2_blue_d);
    document.getElementById("line3_blue").setAttribute("d", line3_blue_d);

    let line1_green_d = `M ${line1_green.begin.x} ${line1_green.begin.y} Q ${line1_green_control.x} ${line1_green_control.y} ${line1_green.end.x} ${line1_green.end.y}`;
    let line2_green_d = `M ${line2_green.begin.x} ${line2_green.begin.y} Q ${line2_green_control.x} ${line2_green_control.y} ${line2_green.end.x} ${line2_green.end.y}`;
    let line3_green_d = `M ${line3_green.begin.x} ${line3_green.begin.y} Q ${line3_green_control.x} ${line3_green_control.y} ${line3_green.end.x} ${line3_green.end.y}`;
    document.getElementById("line1_green").setAttribute("d", line1_green_d);
    document.getElementById("line2_green").setAttribute("d", line2_green_d);
    document.getElementById("line3_green").setAttribute("d", line3_green_d);
</script>

参考链接

菜鸟教程

贝塞尔曲线