Devel
Threads by month
- ----- 2026 -----
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- 38 participants
- 40039 discussions
See individual patches.
Peter Krempa (2):
access: Allow 'node-device.read' permission for anonymous users
libvirt-nodedev: Allow read-only access to virNodeDeviceGetAutostart
src/access/viraccessperm.h | 1 +
src/libvirt-nodedev.c | 1 -
2 files changed, 1 insertion(+), 1 deletion(-)
--
2.39.1
2
4
16 Feb '23
Our 404 error page is a little bit too boring. The solution is to
add more penguins !
This relies on MIT licensed javascript code imported from
https://github.com/VincentGarreau/particles.js
The image is extracted from the existing libvirt logo SVG file.
Signed-off-by: Daniel P. Berrangé <berrange(a)redhat.com>
---
docs/404.html.in | 7 +-
docs/css/libvirt.css | 12 +
docs/js/app.js | 108 +++
docs/js/meson.build | 2 +
docs/js/particles.js | 1541 ++++++++++++++++++++++++++++++++++++++++
docs/logos/meson.build | 2 +
docs/logos/penguin.png | Bin 0 -> 4236 bytes
docs/logos/penguin.svg | 358 ++++++++++
docs/page.xsl | 8 +
9 files changed, 2035 insertions(+), 3 deletions(-)
create mode 100644 docs/js/app.js
create mode 100644 docs/js/particles.js
create mode 100644 docs/logos/penguin.png
create mode 100644 docs/logos/penguin.svg
Yes, this could easily be considered an April Fools' joke, but at
the same time it is common to have a bit of fun with 404 error
pages, so it is also a real suggestion :-)
Live example rendering is at:
https://berrange.gitlab.io/-/libvirt/-/jobs/3749944370/artifacts/website/40…
The main "cost" of the fun is a few 10's of KB more in the dist
from the JS/SVG/PNG
diff --git a/docs/404.html.in b/docs/404.html.in
index 0ac76f125a..39cded58f6 100644
--- a/docs/404.html.in
+++ b/docs/404.html.in
@@ -5,15 +5,16 @@
<h1>404 page not found</h1>
<p>
- Someone appears to have eaten the <del>penguin</del>
- page you were looking for. You might want to try
+ We can't figure out which <del>penguin</del> page you were
+ looking for. You might want to try
</p>
<ul>
<li>going back to the <a href="https://libvirt.org/">home page</a> to find
a collection of links to interesting pages on this site</li>
<li>using the search box at the top right corner of the screen to
locate the content on this site or mailing list archives</li>
+ <li>selecting the right penguin swimming in the pool below</li>
</ul>
-
+ <div id="particles-js"><!-- preserve --></div>
</body>
</html>
diff --git a/docs/css/libvirt.css b/docs/css/libvirt.css
index 097dfcbe8e..fbd193da74 100644
--- a/docs/css/libvirt.css
+++ b/docs/css/libvirt.css
@@ -636,3 +636,15 @@ th p, td p {
#contents p.topic-title {
display: none;
}
+
+canvas {
+ display: block;
+ vertical-align: bottom;
+}
+
+#particles-js {
+ background-color: rgb(230,250,255);
+ border: 2px solid rgb(150,180,255);
+ width: 100%;
+ height: 100%;
+}
diff --git a/docs/js/app.js b/docs/js/app.js
new file mode 100644
index 0000000000..79fae27c2e
--- /dev/null
+++ b/docs/js/app.js
@@ -0,0 +1,108 @@
+particlesJS('particles-js',
+ {
+ "particles": {
+ "number": {
+ "value": 20,
+ "density": {
+ "enable": true,
+ "value_area": 800
+ }
+ },
+ "color": {
+ "value": "#ff0000"
+ },
+ "shape": {
+ "type": "image",
+ "image": {
+ "src": "logos/penguin.png",
+ "width": 73,
+ "height": 138
+ }
+ },
+ "opacity": {
+ "value": 0.5,
+ "random": true,
+ "anim": {
+ "enable": true,
+ "speed": 1,
+ "opacity_min": 0.1,
+ "sync": false
+ }
+ },
+ "size": {
+ "value": 50,
+ "random": true,
+ "anim": {
+ "enable": false,
+ "speed": 40,
+ "size_min": 0.1,
+ "sync": false
+ }
+ },
+ "line_linked": {
+ "enable": false,
+ },
+ "move": {
+ "enable": true,
+ "speed": 6,
+ "direction": "none",
+ "random": false,
+ "straight": false,
+ "out_mode": "bounce",
+ "attract": {
+ "enable": true,
+ "rotateX": 600,
+ "rotateY": 1200
+ }
+ }
+ },
+ "interactivity": {
+ "detect_on": "canvas",
+ "events": {
+ "onhover": {
+ "enable": true,
+ "mode": "repulse"
+ },
+ "onclick": {
+ "enable": true,
+ "mode": "push"
+ },
+ "resize": true
+ },
+ "modes": {
+ "grab": {
+ "distance": 400,
+ "line_linked": {
+ "opacity": 1
+ }
+ },
+ "bubble": {
+ "distance": 400,
+ "size": 40,
+ "duration": 2,
+ "opacity": 8,
+ "speed": 3
+ },
+ "repulse": {
+ "distance": 200
+ },
+ "push": {
+ "particles_nb": 4
+ },
+ "remove": {
+ "particles_nb": 2
+ }
+ }
+ },
+ "retina_detect": true,
+ "config_demo": {
+ "hide_card": false,
+ "background_color": "#b61924",
+ "background_image": "",
+ "background_position": "50% 50%",
+ "background_repeat": "no-repeat",
+ "background_size": "cover"
+ }
+ }
+
+);
diff --git a/docs/js/meson.build b/docs/js/meson.build
index cbf2dc2633..4e3e05bf89 100644
--- a/docs/js/meson.build
+++ b/docs/js/meson.build
@@ -1,5 +1,7 @@
docs_js_files = [
'main.js',
+ 'particles.js',
+ 'app.js'
]
install_data(docs_js_files, install_dir: docs_html_dir / 'js')
diff --git a/docs/js/particles.js b/docs/js/particles.js
new file mode 100644
index 0000000000..ef3917fab7
--- /dev/null
+++ b/docs/js/particles.js
@@ -0,0 +1,1541 @@
+/* -----------------------------------------------
+/* Author : Vincent Garreau - vincentgarreau.com
+/* MIT license: https://opensource.org/licenses/MIT
+/* Demo / Generator : vincentgarreau.com/particles.js
+/* GitHub : github.com/VincentGarreau/particles.js
+/* How to use? : Check the GitHub README
+/* v2.0.0
+/* ----------------------------------------------- */
+
+var pJS = function(tag_id, params){
+
+ var canvas_el = document.querySelector('#'+tag_id+' > .particles-js-canvas-el');
+
+ /* particles.js variables with default values */
+ this.pJS = {
+ canvas: {
+ el: canvas_el,
+ w: canvas_el.offsetWidth,
+ h: canvas_el.offsetHeight
+ },
+ particles: {
+ number: {
+ value: 400,
+ density: {
+ enable: true,
+ value_area: 800
+ }
+ },
+ color: {
+ value: '#fff'
+ },
+ shape: {
+ type: 'circle',
+ stroke: {
+ width: 0,
+ color: '#ff0000'
+ },
+ polygon: {
+ nb_sides: 5
+ },
+ image: {
+ src: '',
+ width: 100,
+ height: 100
+ }
+ },
+ opacity: {
+ value: 1,
+ random: false,
+ anim: {
+ enable: false,
+ speed: 2,
+ opacity_min: 0,
+ sync: false
+ }
+ },
+ size: {
+ value: 20,
+ random: false,
+ anim: {
+ enable: false,
+ speed: 20,
+ size_min: 0,
+ sync: false
+ }
+ },
+ line_linked: {
+ enable: true,
+ distance: 100,
+ color: '#fff',
+ opacity: 1,
+ width: 1
+ },
+ move: {
+ enable: true,
+ speed: 2,
+ direction: 'none',
+ random: false,
+ straight: false,
+ out_mode: 'out',
+ bounce: false,
+ attract: {
+ enable: false,
+ rotateX: 3000,
+ rotateY: 3000
+ }
+ },
+ array: []
+ },
+ interactivity: {
+ detect_on: 'canvas',
+ events: {
+ onhover: {
+ enable: true,
+ mode: 'grab'
+ },
+ onclick: {
+ enable: true,
+ mode: 'push'
+ },
+ resize: true
+ },
+ modes: {
+ grab:{
+ distance: 100,
+ line_linked:{
+ opacity: 1
+ }
+ },
+ bubble:{
+ distance: 200,
+ size: 80,
+ duration: 0.4
+ },
+ repulse:{
+ distance: 200,
+ duration: 0.4
+ },
+ push:{
+ particles_nb: 4
+ },
+ remove:{
+ particles_nb: 2
+ }
+ },
+ mouse:{}
+ },
+ retina_detect: false,
+ fn: {
+ interact: {},
+ modes: {},
+ vendors:{}
+ },
+ tmp: {}
+ };
+
+ var pJS = this.pJS;
+
+ /* params settings */
+ if(params){
+ Object.deepExtend(pJS, params);
+ }
+
+ pJS.tmp.obj = {
+ size_value: pJS.particles.size.value,
+ size_anim_speed: pJS.particles.size.anim.speed,
+ move_speed: pJS.particles.move.speed,
+ line_linked_distance: pJS.particles.line_linked.distance,
+ line_linked_width: pJS.particles.line_linked.width,
+ mode_grab_distance: pJS.interactivity.modes.grab.distance,
+ mode_bubble_distance: pJS.interactivity.modes.bubble.distance,
+ mode_bubble_size: pJS.interactivity.modes.bubble.size,
+ mode_repulse_distance: pJS.interactivity.modes.repulse.distance
+ };
+
+
+ pJS.fn.retinaInit = function(){
+
+ if(pJS.retina_detect && window.devicePixelRatio > 1){
+ pJS.canvas.pxratio = window.devicePixelRatio;
+ pJS.tmp.retina = true;
+ }
+ else{
+ pJS.canvas.pxratio = 1;
+ pJS.tmp.retina = false;
+ }
+
+ pJS.canvas.w = pJS.canvas.el.offsetWidth * pJS.canvas.pxratio;
+ pJS.canvas.h = pJS.canvas.el.offsetHeight * pJS.canvas.pxratio;
+
+ pJS.particles.size.value = pJS.tmp.obj.size_value * pJS.canvas.pxratio;
+ pJS.particles.size.anim.speed = pJS.tmp.obj.size_anim_speed * pJS.canvas.pxratio;
+ pJS.particles.move.speed = pJS.tmp.obj.move_speed * pJS.canvas.pxratio;
+ pJS.particles.line_linked.distance = pJS.tmp.obj.line_linked_distance * pJS.canvas.pxratio;
+ pJS.interactivity.modes.grab.distance = pJS.tmp.obj.mode_grab_distance * pJS.canvas.pxratio;
+ pJS.interactivity.modes.bubble.distance = pJS.tmp.obj.mode_bubble_distance * pJS.canvas.pxratio;
+ pJS.particles.line_linked.width = pJS.tmp.obj.line_linked_width * pJS.canvas.pxratio;
+ pJS.interactivity.modes.bubble.size = pJS.tmp.obj.mode_bubble_size * pJS.canvas.pxratio;
+ pJS.interactivity.modes.repulse.distance = pJS.tmp.obj.mode_repulse_distance * pJS.canvas.pxratio;
+
+ };
+
+
+
+ /* ---------- pJS functions - canvas ------------ */
+
+ pJS.fn.canvasInit = function(){
+ pJS.canvas.ctx = pJS.canvas.el.getContext('2d');
+ };
+
+ pJS.fn.canvasSize = function(){
+
+ pJS.canvas.el.width = pJS.canvas.w;
+ pJS.canvas.el.height = pJS.canvas.h;
+
+ if(pJS && pJS.interactivity.events.resize){
+
+ window.addEventListener('resize', function(){
+
+ pJS.canvas.w = pJS.canvas.el.offsetWidth;
+ pJS.canvas.h = pJS.canvas.el.offsetHeight;
+
+ /* resize canvas */
+ if(pJS.tmp.retina){
+ pJS.canvas.w *= pJS.canvas.pxratio;
+ pJS.canvas.h *= pJS.canvas.pxratio;
+ }
+
+ pJS.canvas.el.width = pJS.canvas.w;
+ pJS.canvas.el.height = pJS.canvas.h;
+
+ /* repaint canvas on anim disabled */
+ if(!pJS.particles.move.enable){
+ pJS.fn.particlesEmpty();
+ pJS.fn.particlesCreate();
+ pJS.fn.particlesDraw();
+ pJS.fn.vendors.densityAutoParticles();
+ }
+
+ /* density particles enabled */
+ pJS.fn.vendors.densityAutoParticles();
+
+ });
+
+ }
+
+ };
+
+
+ pJS.fn.canvasPaint = function(){
+ pJS.canvas.ctx.fillRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+ };
+
+ pJS.fn.canvasClear = function(){
+ pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+ };
+
+
+ /* --------- pJS functions - particles ----------- */
+
+ pJS.fn.particle = function(color, opacity, position){
+
+ /* size */
+ this.radius = (pJS.particles.size.random ? Math.random() : 1) * pJS.particles.size.value;
+ if(pJS.particles.size.anim.enable){
+ this.size_status = false;
+ this.vs = pJS.particles.size.anim.speed / 100;
+ if(!pJS.particles.size.anim.sync){
+ this.vs = this.vs * Math.random();
+ }
+ }
+
+ /* position */
+ this.x = position ? position.x : Math.random() * pJS.canvas.w;
+ this.y = position ? position.y : Math.random() * pJS.canvas.h;
+
+ /* check position - into the canvas */
+ if(this.x > pJS.canvas.w - this.radius*2) this.x = this.x - this.radius;
+ else if(this.x < this.radius*2) this.x = this.x + this.radius;
+ if(this.y > pJS.canvas.h - this.radius*2) this.y = this.y - this.radius;
+ else if(this.y < this.radius*2) this.y = this.y + this.radius;
+
+ /* check position - avoid overlap */
+ if(pJS.particles.move.bounce){
+ pJS.fn.vendors.checkOverlap(this, position);
+ }
+
+ /* color */
+ this.color = {};
+ if(typeof(color.value) == 'object'){
+
+ if(color.value instanceof Array){
+ var color_selected = color.value[Math.floor(Math.random() * pJS.particles.color.value.length)];
+ this.color.rgb = hexToRgb(color_selected);
+ }else{
+ if(color.value.r != undefined && color.value.g != undefined && color.value.b != undefined){
+ this.color.rgb = {
+ r: color.value.r,
+ g: color.value.g,
+ b: color.value.b
+ }
+ }
+ if(color.value.h != undefined && color.value.s != undefined && color.value.l != undefined){
+ this.color.hsl = {
+ h: color.value.h,
+ s: color.value.s,
+ l: color.value.l
+ }
+ }
+ }
+
+ }
+ else if(color.value == 'random'){
+ this.color.rgb = {
+ r: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
+ g: (Math.floor(Math.random() * (255 - 0 + 1)) + 0),
+ b: (Math.floor(Math.random() * (255 - 0 + 1)) + 0)
+ }
+ }
+ else if(typeof(color.value) == 'string'){
+ this.color = color;
+ this.color.rgb = hexToRgb(this.color.value);
+ }
+
+ /* opacity */
+ this.opacity = (pJS.particles.opacity.random ? Math.random() : 1) * pJS.particles.opacity.value;
+ if(pJS.particles.opacity.anim.enable){
+ this.opacity_status = false;
+ this.vo = pJS.particles.opacity.anim.speed / 100;
+ if(!pJS.particles.opacity.anim.sync){
+ this.vo = this.vo * Math.random();
+ }
+ }
+
+ /* animation - velocity for speed */
+ var velbase = {}
+ switch(pJS.particles.move.direction){
+ case 'top':
+ velbase = { x:0, y:-1 };
+ break;
+ case 'top-right':
+ velbase = { x:0.5, y:-0.5 };
+ break;
+ case 'right':
+ velbase = { x:1, y:-0 };
+ break;
+ case 'bottom-right':
+ velbase = { x:0.5, y:0.5 };
+ break;
+ case 'bottom':
+ velbase = { x:0, y:1 };
+ break;
+ case 'bottom-left':
+ velbase = { x:-0.5, y:1 };
+ break;
+ case 'left':
+ velbase = { x:-1, y:0 };
+ break;
+ case 'top-left':
+ velbase = { x:-0.5, y:-0.5 };
+ break;
+ default:
+ velbase = { x:0, y:0 };
+ break;
+ }
+
+ if(pJS.particles.move.straight){
+ this.vx = velbase.x;
+ this.vy = velbase.y;
+ if(pJS.particles.move.random){
+ this.vx = this.vx * (Math.random());
+ this.vy = this.vy * (Math.random());
+ }
+ }else{
+ this.vx = velbase.x + Math.random()-0.5;
+ this.vy = velbase.y + Math.random()-0.5;
+ }
+
+ // var theta = 2.0 * Math.PI * Math.random();
+ // this.vx = Math.cos(theta);
+ // this.vy = Math.sin(theta);
+
+ this.vx_i = this.vx;
+ this.vy_i = this.vy;
+
+
+
+ /* if shape is image */
+
+ var shape_type = pJS.particles.shape.type;
+ if(typeof(shape_type) == 'object'){
+ if(shape_type instanceof Array){
+ var shape_selected = shape_type[Math.floor(Math.random() * shape_type.length)];
+ this.shape = shape_selected;
+ }
+ }else{
+ this.shape = shape_type;
+ }
+
+ if(this.shape == 'image'){
+ var sh = pJS.particles.shape;
+ this.img = {
+ src: sh.image.src,
+ ratio: sh.image.width / sh.image.height
+ }
+ if(!this.img.ratio) this.img.ratio = 1;
+ if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg != undefined){
+ pJS.fn.vendors.createSvgImg(this);
+ if(pJS.tmp.pushing){
+ this.img.loaded = false;
+ }
+ }
+ }
+
+
+
+ };
+
+
+ pJS.fn.particle.prototype.draw = function() {
+
+ var p = this;
+
+ if(p.radius_bubble != undefined){
+ var radius = p.radius_bubble;
+ }else{
+ var radius = p.radius;
+ }
+
+ if(p.opacity_bubble != undefined){
+ var opacity = p.opacity_bubble;
+ }else{
+ var opacity = p.opacity;
+ }
+
+ if(p.color.rgb){
+ var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+opacity+')';
+ }else{
+ var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+opacity+')';
+ }
+
+ pJS.canvas.ctx.fillStyle = color_value;
+ pJS.canvas.ctx.beginPath();
+
+ switch(p.shape){
+
+ case 'circle':
+ pJS.canvas.ctx.arc(p.x, p.y, radius, 0, Math.PI * 2, false);
+ break;
+
+ case 'edge':
+ pJS.canvas.ctx.rect(p.x-radius, p.y-radius, radius*2, radius*2);
+ break;
+
+ case 'triangle':
+ pJS.fn.vendors.drawShape(pJS.canvas.ctx, p.x-radius, p.y+radius / 1.66, radius*2, 3, 2);
+ break;
+
+ case 'polygon':
+ pJS.fn.vendors.drawShape(
+ pJS.canvas.ctx,
+ p.x - radius / (pJS.particles.shape.polygon.nb_sides/3.5), // startX
+ p.y - radius / (2.66/3.5), // startY
+ radius*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength
+ pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
+ 1 // sideCountDenominator
+ );
+ break;
+
+ case 'star':
+ pJS.fn.vendors.drawShape(
+ pJS.canvas.ctx,
+ p.x - radius*2 / (pJS.particles.shape.polygon.nb_sides/4), // startX
+ p.y - radius / (2*2.66/3.5), // startY
+ radius*2*2.66 / (pJS.particles.shape.polygon.nb_sides/3), // sideLength
+ pJS.particles.shape.polygon.nb_sides, // sideCountNumerator
+ 2 // sideCountDenominator
+ );
+ break;
+
+ case 'image':
+
+ function draw(){
+ pJS.canvas.ctx.drawImage(
+ img_obj,
+ p.x-radius,
+ p.y-radius,
+ radius*2,
+ radius*2 / p.img.ratio
+ );
+ }
+
+ if(pJS.tmp.img_type == 'svg'){
+ var img_obj = p.img.obj;
+ }else{
+ var img_obj = pJS.tmp.img_obj;
+ }
+
+ if(img_obj){
+ draw();
+ }
+
+ break;
+
+ }
+
+ pJS.canvas.ctx.closePath();
+
+ if(pJS.particles.shape.stroke.width > 0){
+ pJS.canvas.ctx.strokeStyle = pJS.particles.shape.stroke.color;
+ pJS.canvas.ctx.lineWidth = pJS.particles.shape.stroke.width;
+ pJS.canvas.ctx.stroke();
+ }
+
+ pJS.canvas.ctx.fill();
+
+ };
+
+
+ pJS.fn.particlesCreate = function(){
+ for(var i = 0; i < pJS.particles.number.value; i++) {
+ pJS.particles.array.push(new pJS.fn.particle(pJS.particles.color, pJS.particles.opacity.value));
+ }
+ };
+
+ pJS.fn.particlesUpdate = function(){
+
+ for(var i = 0; i < pJS.particles.array.length; i++){
+
+ /* the particle */
+ var p = pJS.particles.array[i];
+
+ // var d = ( dx = pJS.interactivity.mouse.click_pos_x - p.x ) * dx + ( dy = pJS.interactivity.mouse.click_pos_y - p.y ) * dy;
+ // var f = -BANG_SIZE / d;
+ // if ( d < BANG_SIZE ) {
+ // var t = Math.atan2( dy, dx );
+ // p.vx = f * Math.cos(t);
+ // p.vy = f * Math.sin(t);
+ // }
+
+ /* move the particle */
+ if(pJS.particles.move.enable){
+ var ms = pJS.particles.move.speed/2;
+ p.x += p.vx * ms;
+ p.y += p.vy * ms;
+ }
+
+ /* change opacity status */
+ if(pJS.particles.opacity.anim.enable) {
+ if(p.opacity_status == true) {
+ if(p.opacity >= pJS.particles.opacity.value) p.opacity_status = false;
+ p.opacity += p.vo;
+ }else {
+ if(p.opacity <= pJS.particles.opacity.anim.opacity_min) p.opacity_status = true;
+ p.opacity -= p.vo;
+ }
+ if(p.opacity < 0) p.opacity = 0;
+ }
+
+ /* change size */
+ if(pJS.particles.size.anim.enable){
+ if(p.size_status == true){
+ if(p.radius >= pJS.particles.size.value) p.size_status = false;
+ p.radius += p.vs;
+ }else{
+ if(p.radius <= pJS.particles.size.anim.size_min) p.size_status = true;
+ p.radius -= p.vs;
+ }
+ if(p.radius < 0) p.radius = 0;
+ }
+
+ /* change particle position if it is out of canvas */
+ if(pJS.particles.move.out_mode == 'bounce'){
+ var new_pos = {
+ x_left: p.radius,
+ x_right: pJS.canvas.w,
+ y_top: p.radius,
+ y_bottom: pJS.canvas.h
+ }
+ }else{
+ var new_pos = {
+ x_left: -p.radius,
+ x_right: pJS.canvas.w + p.radius,
+ y_top: -p.radius,
+ y_bottom: pJS.canvas.h + p.radius
+ }
+ }
+
+ if(p.x - p.radius > pJS.canvas.w){
+ p.x = new_pos.x_left;
+ p.y = Math.random() * pJS.canvas.h;
+ }
+ else if(p.x + p.radius < 0){
+ p.x = new_pos.x_right;
+ p.y = Math.random() * pJS.canvas.h;
+ }
+ if(p.y - p.radius > pJS.canvas.h){
+ p.y = new_pos.y_top;
+ p.x = Math.random() * pJS.canvas.w;
+ }
+ else if(p.y + p.radius < 0){
+ p.y = new_pos.y_bottom;
+ p.x = Math.random() * pJS.canvas.w;
+ }
+
+ /* out of canvas modes */
+ switch(pJS.particles.move.out_mode){
+ case 'bounce':
+ if (p.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
+ else if (p.x - p.radius < 0) p.vx = -p.vx;
+ if (p.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
+ else if (p.y - p.radius < 0) p.vy = -p.vy;
+ break;
+ }
+
+ /* events */
+ if(isInArray('grab', pJS.interactivity.events.onhover.mode)){
+ pJS.fn.modes.grabParticle(p);
+ }
+
+ if(isInArray('bubble', pJS.interactivity.events.onhover.mode) || isInArray('bubble', pJS.interactivity.events.onclick.mode)){
+ pJS.fn.modes.bubbleParticle(p);
+ }
+
+ if(isInArray('repulse', pJS.interactivity.events.onhover.mode) || isInArray('repulse', pJS.interactivity.events.onclick.mode)){
+ pJS.fn.modes.repulseParticle(p);
+ }
+
+ /* interaction auto between particles */
+ if(pJS.particles.line_linked.enable || pJS.particles.move.attract.enable){
+ for(var j = i + 1; j < pJS.particles.array.length; j++){
+ var p2 = pJS.particles.array[j];
+
+ /* link particles */
+ if(pJS.particles.line_linked.enable){
+ pJS.fn.interact.linkParticles(p,p2);
+ }
+
+ /* attract particles */
+ if(pJS.particles.move.attract.enable){
+ pJS.fn.interact.attractParticles(p,p2);
+ }
+
+ /* bounce particles */
+ if(pJS.particles.move.bounce){
+ pJS.fn.interact.bounceParticles(p,p2);
+ }
+
+ }
+ }
+
+
+ }
+
+ };
+
+ pJS.fn.particlesDraw = function(){
+
+ /* clear canvas */
+ pJS.canvas.ctx.clearRect(0, 0, pJS.canvas.w, pJS.canvas.h);
+
+ /* update each particles param */
+ pJS.fn.particlesUpdate();
+
+ /* draw each particle */
+ for(var i = 0; i < pJS.particles.array.length; i++){
+ var p = pJS.particles.array[i];
+ p.draw();
+ }
+
+ };
+
+ pJS.fn.particlesEmpty = function(){
+ pJS.particles.array = [];
+ };
+
+ pJS.fn.particlesRefresh = function(){
+
+ /* init all */
+ cancelRequestAnimFrame(pJS.fn.checkAnimFrame);
+ cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ pJS.tmp.source_svg = undefined;
+ pJS.tmp.img_obj = undefined;
+ pJS.tmp.count_svg = 0;
+ pJS.fn.particlesEmpty();
+ pJS.fn.canvasClear();
+
+ /* restart */
+ pJS.fn.vendors.start();
+
+ };
+
+
+ /* ---------- pJS functions - particles interaction ------------ */
+
+ pJS.fn.interact.linkParticles = function(p1, p2){
+
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx*dx + dy*dy);
+
+ /* draw a line between p1 and p2 if the distance between them is under the config distance */
+ if(dist <= pJS.particles.line_linked.distance){
+
+ var opacity_line = pJS.particles.line_linked.opacity - (dist / (1/pJS.particles.line_linked.opacity)) / pJS.particles.line_linked.distance;
+
+ if(opacity_line > 0){
+
+ /* style */
+ var color_line = pJS.particles.line_linked.color_rgb_line;
+ pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';
+ pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
+ //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
+
+ /* path */
+ pJS.canvas.ctx.beginPath();
+ pJS.canvas.ctx.moveTo(p1.x, p1.y);
+ pJS.canvas.ctx.lineTo(p2.x, p2.y);
+ pJS.canvas.ctx.stroke();
+ pJS.canvas.ctx.closePath();
+
+ }
+
+ }
+
+ };
+
+
+ pJS.fn.interact.attractParticles = function(p1, p2){
+
+ /* condensed particles */
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx*dx + dy*dy);
+
+ if(dist <= pJS.particles.line_linked.distance){
+
+ var ax = dx/(pJS.particles.move.attract.rotateX*1000),
+ ay = dy/(pJS.particles.move.attract.rotateY*1000);
+
+ p1.vx -= ax;
+ p1.vy -= ay;
+
+ p2.vx += ax;
+ p2.vy += ay;
+
+ }
+
+
+ }
+
+
+ pJS.fn.interact.bounceParticles = function(p1, p2){
+
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx*dx + dy*dy),
+ dist_p = p1.radius+p2.radius;
+
+ if(dist <= dist_p){
+ p1.vx = -p1.vx;
+ p1.vy = -p1.vy;
+
+ p2.vx = -p2.vx;
+ p2.vy = -p2.vy;
+ }
+
+ }
+
+
+ /* ---------- pJS functions - modes events ------------ */
+
+ pJS.fn.modes.pushParticles = function(nb, pos){
+
+ pJS.tmp.pushing = true;
+
+ for(var i = 0; i < nb; i++){
+ pJS.particles.array.push(
+ new pJS.fn.particle(
+ pJS.particles.color,
+ pJS.particles.opacity.value,
+ {
+ 'x': pos ? pos.pos_x : Math.random() * pJS.canvas.w,
+ 'y': pos ? pos.pos_y : Math.random() * pJS.canvas.h
+ }
+ )
+ )
+ if(i == nb-1){
+ if(!pJS.particles.move.enable){
+ pJS.fn.particlesDraw();
+ }
+ pJS.tmp.pushing = false;
+ }
+ }
+
+ };
+
+
+ pJS.fn.modes.removeParticles = function(nb){
+
+ pJS.particles.array.splice(0, nb);
+ if(!pJS.particles.move.enable){
+ pJS.fn.particlesDraw();
+ }
+
+ };
+
+
+ pJS.fn.modes.bubbleParticle = function(p){
+
+ /* on hover event */
+ if(pJS.interactivity.events.onhover.enable && isInArray('bubble', pJS.interactivity.events.onhover.mode)){
+
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),
+ ratio = 1 - dist_mouse / pJS.interactivity.modes.bubble.distance;
+
+ function init(){
+ p.opacity_bubble = p.opacity;
+ p.radius_bubble = p.radius;
+ }
+
+ /* mousemove - check ratio */
+ if(dist_mouse <= pJS.interactivity.modes.bubble.distance){
+
+ if(ratio >= 0 && pJS.interactivity.status == 'mousemove'){
+
+ /* size */
+ if(pJS.interactivity.modes.bubble.size != pJS.particles.size.value){
+
+ if(pJS.interactivity.modes.bubble.size > pJS.particles.size.value){
+ var size = p.radius + (pJS.interactivity.modes.bubble.size*ratio);
+ if(size >= 0){
+ p.radius_bubble = size;
+ }
+ }else{
+ var dif = p.radius - pJS.interactivity.modes.bubble.size,
+ size = p.radius - (dif*ratio);
+ if(size > 0){
+ p.radius_bubble = size;
+ }else{
+ p.radius_bubble = 0;
+ }
+ }
+
+ }
+
+ /* opacity */
+ if(pJS.interactivity.modes.bubble.opacity != pJS.particles.opacity.value){
+
+ if(pJS.interactivity.modes.bubble.opacity > pJS.particles.opacity.value){
+ var opacity = pJS.interactivity.modes.bubble.opacity*ratio;
+ if(opacity > p.opacity && opacity <= pJS.interactivity.modes.bubble.opacity){
+ p.opacity_bubble = opacity;
+ }
+ }else{
+ var opacity = p.opacity - (pJS.particles.opacity.value-pJS.interactivity.modes.bubble.opacity)*ratio;
+ if(opacity < p.opacity && opacity >= pJS.interactivity.modes.bubble.opacity){
+ p.opacity_bubble = opacity;
+ }
+ }
+
+ }
+
+ }
+
+ }else{
+ init();
+ }
+
+
+ /* mouseleave */
+ if(pJS.interactivity.status == 'mouseleave'){
+ init();
+ }
+
+ }
+
+ /* on click event */
+ else if(pJS.interactivity.events.onclick.enable && isInArray('bubble', pJS.interactivity.events.onclick.mode)){
+
+
+ if(pJS.tmp.bubble_clicking){
+ var dx_mouse = p.x - pJS.interactivity.mouse.click_pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.click_pos_y,
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse),
+ time_spent = (new Date().getTime() - pJS.interactivity.mouse.click_time)/1000;
+
+ if(time_spent > pJS.interactivity.modes.bubble.duration){
+ pJS.tmp.bubble_duration_end = true;
+ }
+
+ if(time_spent > pJS.interactivity.modes.bubble.duration*2){
+ pJS.tmp.bubble_clicking = false;
+ pJS.tmp.bubble_duration_end = false;
+ }
+ }
+
+
+ function process(bubble_param, particles_param, p_obj_bubble, p_obj, id){
+
+ if(bubble_param != particles_param){
+
+ if(!pJS.tmp.bubble_duration_end){
+ if(dist_mouse <= pJS.interactivity.modes.bubble.distance){
+ if(p_obj_bubble != undefined) var obj = p_obj_bubble;
+ else var obj = p_obj;
+ if(obj != bubble_param){
+ var value = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration);
+ if(id == 'size') p.radius_bubble = value;
+ if(id == 'opacity') p.opacity_bubble = value;
+ }
+ }else{
+ if(id == 'size') p.radius_bubble = undefined;
+ if(id == 'opacity') p.opacity_bubble = undefined;
+ }
+ }else{
+ if(p_obj_bubble != undefined){
+ var value_tmp = p_obj - (time_spent * (p_obj - bubble_param) / pJS.interactivity.modes.bubble.duration),
+ dif = bubble_param - value_tmp;
+ value = bubble_param + dif;
+ if(id == 'size') p.radius_bubble = value;
+ if(id == 'opacity') p.opacity_bubble = value;
+ }
+ }
+
+ }
+
+ }
+
+ if(pJS.tmp.bubble_clicking){
+ /* size */
+ process(pJS.interactivity.modes.bubble.size, pJS.particles.size.value, p.radius_bubble, p.radius, 'size');
+ /* opacity */
+ process(pJS.interactivity.modes.bubble.opacity, pJS.particles.opacity.value, p.opacity_bubble, p.opacity, 'opacity');
+ }
+
+ }
+
+ };
+
+
+ pJS.fn.modes.repulseParticle = function(p){
+
+ if(pJS.interactivity.events.onhover.enable && isInArray('repulse', pJS.interactivity.events.onhover.mode) && pJS.interactivity.status == 'mousemove') {
+
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);
+
+ var normVec = {x: dx_mouse/dist_mouse, y: dy_mouse/dist_mouse},
+ repulseRadius = pJS.interactivity.modes.repulse.distance,
+ velocity = 100,
+ repulseFactor = clamp((1/repulseRadius)*(-1*Math.pow(dist_mouse/repulseRadius,2)+1)*repulseRadius*velocity, 0, 50);
+
+ var pos = {
+ x: p.x + normVec.x * repulseFactor,
+ y: p.y + normVec.y * repulseFactor
+ }
+
+ if(pJS.particles.move.out_mode == 'bounce'){
+ if(pos.x - p.radius > 0 && pos.x + p.radius < pJS.canvas.w) p.x = pos.x;
+ if(pos.y - p.radius > 0 && pos.y + p.radius < pJS.canvas.h) p.y = pos.y;
+ }else{
+ p.x = pos.x;
+ p.y = pos.y;
+ }
+
+ }
+
+
+ else if(pJS.interactivity.events.onclick.enable && isInArray('repulse', pJS.interactivity.events.onclick.mode)) {
+
+ if(!pJS.tmp.repulse_finish){
+ pJS.tmp.repulse_count++;
+ if(pJS.tmp.repulse_count == pJS.particles.array.length){
+ pJS.tmp.repulse_finish = true;
+ }
+ }
+
+ if(pJS.tmp.repulse_clicking){
+
+ var repulseRadius = Math.pow(pJS.interactivity.modes.repulse.distance/6, 3);
+
+ var dx = pJS.interactivity.mouse.click_pos_x - p.x,
+ dy = pJS.interactivity.mouse.click_pos_y - p.y,
+ d = dx*dx + dy*dy;
+
+ var force = -repulseRadius / d * 1;
+
+ function process(){
+
+ var f = Math.atan2(dy,dx);
+ p.vx = force * Math.cos(f);
+ p.vy = force * Math.sin(f);
+
+ if(pJS.particles.move.out_mode == 'bounce'){
+ var pos = {
+ x: p.x + p.vx,
+ y: p.y + p.vy
+ }
+ if (pos.x + p.radius > pJS.canvas.w) p.vx = -p.vx;
+ else if (pos.x - p.radius < 0) p.vx = -p.vx;
+ if (pos.y + p.radius > pJS.canvas.h) p.vy = -p.vy;
+ else if (pos.y - p.radius < 0) p.vy = -p.vy;
+ }
+
+ }
+
+ // default
+ if(d <= repulseRadius){
+ process();
+ }
+
+ // bang - slow motion mode
+ // if(!pJS.tmp.repulse_finish){
+ // if(d <= repulseRadius){
+ // process();
+ // }
+ // }else{
+ // process();
+ // }
+
+
+ }else{
+
+ if(pJS.tmp.repulse_clicking == false){
+
+ p.vx = p.vx_i;
+ p.vy = p.vy_i;
+
+ }
+
+ }
+
+ }
+
+ }
+
+
+ pJS.fn.modes.grabParticle = function(p){
+
+ if(pJS.interactivity.events.onhover.enable && pJS.interactivity.status == 'mousemove'){
+
+ var dx_mouse = p.x - pJS.interactivity.mouse.pos_x,
+ dy_mouse = p.y - pJS.interactivity.mouse.pos_y,
+ dist_mouse = Math.sqrt(dx_mouse*dx_mouse + dy_mouse*dy_mouse);
+
+ /* draw a line between the cursor and the particle if the distance between them is under the config distance */
+ if(dist_mouse <= pJS.interactivity.modes.grab.distance){
+
+ var opacity_line = pJS.interactivity.modes.grab.line_linked.opacity - (dist_mouse / (1/pJS.interactivity.modes.grab.line_linked.opacity)) / pJS.interactivity.modes.grab.distance;
+
+ if(opacity_line > 0){
+
+ /* style */
+ var color_line = pJS.particles.line_linked.color_rgb_line;
+ pJS.canvas.ctx.strokeStyle = 'rgba('+color_line.r+','+color_line.g+','+color_line.b+','+opacity_line+')';
+ pJS.canvas.ctx.lineWidth = pJS.particles.line_linked.width;
+ //pJS.canvas.ctx.lineCap = 'round'; /* performance issue */
+
+ /* path */
+ pJS.canvas.ctx.beginPath();
+ pJS.canvas.ctx.moveTo(p.x, p.y);
+ pJS.canvas.ctx.lineTo(pJS.interactivity.mouse.pos_x, pJS.interactivity.mouse.pos_y);
+ pJS.canvas.ctx.stroke();
+ pJS.canvas.ctx.closePath();
+
+ }
+
+ }
+
+ }
+
+ };
+
+
+
+ /* ---------- pJS functions - vendors ------------ */
+
+ pJS.fn.vendors.eventsListeners = function(){
+
+ /* events target element */
+ if(pJS.interactivity.detect_on == 'window'){
+ pJS.interactivity.el = window;
+ }else{
+ pJS.interactivity.el = pJS.canvas.el;
+ }
+
+
+ /* detect mouse pos - on hover / click event */
+ if(pJS.interactivity.events.onhover.enable || pJS.interactivity.events.onclick.enable){
+
+ /* el on mousemove */
+ pJS.interactivity.el.addEventListener('mousemove', function(e){
+
+ if(pJS.interactivity.el == window){
+ var pos_x = e.clientX,
+ pos_y = e.clientY;
+ }
+ else{
+ var pos_x = e.offsetX || e.clientX,
+ pos_y = e.offsetY || e.clientY;
+ }
+
+ pJS.interactivity.mouse.pos_x = pos_x;
+ pJS.interactivity.mouse.pos_y = pos_y;
+
+ if(pJS.tmp.retina){
+ pJS.interactivity.mouse.pos_x *= pJS.canvas.pxratio;
+ pJS.interactivity.mouse.pos_y *= pJS.canvas.pxratio;
+ }
+
+ pJS.interactivity.status = 'mousemove';
+
+ });
+
+ /* el on onmouseleave */
+ pJS.interactivity.el.addEventListener('mouseleave', function(e){
+
+ pJS.interactivity.mouse.pos_x = null;
+ pJS.interactivity.mouse.pos_y = null;
+ pJS.interactivity.status = 'mouseleave';
+
+ });
+
+ }
+
+ /* on click event */
+ if(pJS.interactivity.events.onclick.enable){
+
+ pJS.interactivity.el.addEventListener('click', function(){
+
+ pJS.interactivity.mouse.click_pos_x = pJS.interactivity.mouse.pos_x;
+ pJS.interactivity.mouse.click_pos_y = pJS.interactivity.mouse.pos_y;
+ pJS.interactivity.mouse.click_time = new Date().getTime();
+
+ if(pJS.interactivity.events.onclick.enable){
+
+ switch(pJS.interactivity.events.onclick.mode){
+
+ case 'push':
+ if(pJS.particles.move.enable){
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
+ }else{
+ if(pJS.interactivity.modes.push.particles_nb == 1){
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb, pJS.interactivity.mouse);
+ }
+ else if(pJS.interactivity.modes.push.particles_nb > 1){
+ pJS.fn.modes.pushParticles(pJS.interactivity.modes.push.particles_nb);
+ }
+ }
+ break;
+
+ case 'remove':
+ pJS.fn.modes.removeParticles(pJS.interactivity.modes.remove.particles_nb);
+ break;
+
+ case 'bubble':
+ pJS.tmp.bubble_clicking = true;
+ break;
+
+ case 'repulse':
+ pJS.tmp.repulse_clicking = true;
+ pJS.tmp.repulse_count = 0;
+ pJS.tmp.repulse_finish = false;
+ setTimeout(function(){
+ pJS.tmp.repulse_clicking = false;
+ }, pJS.interactivity.modes.repulse.duration*1000)
+ break;
+
+ }
+
+ }
+
+ });
+
+ }
+
+
+ };
+
+ pJS.fn.vendors.densityAutoParticles = function(){
+
+ if(pJS.particles.number.density.enable){
+
+ /* calc area */
+ var area = pJS.canvas.el.width * pJS.canvas.el.height / 1000;
+ if(pJS.tmp.retina){
+ area = area/(pJS.canvas.pxratio*2);
+ }
+
+ /* calc number of particles based on density area */
+ var nb_particles = area * pJS.particles.number.value / pJS.particles.number.density.value_area;
+
+ /* add or remove X particles */
+ var missing_particles = pJS.particles.array.length - nb_particles;
+ if(missing_particles < 0) pJS.fn.modes.pushParticles(Math.abs(missing_particles));
+ else pJS.fn.modes.removeParticles(missing_particles);
+
+ }
+
+ };
+
+
+ pJS.fn.vendors.checkOverlap = function(p1, position){
+ for(var i = 0; i < pJS.particles.array.length; i++){
+ var p2 = pJS.particles.array[i];
+
+ var dx = p1.x - p2.x,
+ dy = p1.y - p2.y,
+ dist = Math.sqrt(dx*dx + dy*dy);
+
+ if(dist <= p1.radius + p2.radius){
+ p1.x = position ? position.x : Math.random() * pJS.canvas.w;
+ p1.y = position ? position.y : Math.random() * pJS.canvas.h;
+ pJS.fn.vendors.checkOverlap(p1);
+ }
+ }
+ };
+
+
+ pJS.fn.vendors.createSvgImg = function(p){
+
+ /* set color to svg element */
+ var svgXml = pJS.tmp.source_svg,
+ rgbHex = /#([0-9A-F]{3,6})/gi,
+ coloredSvgXml = svgXml.replace(rgbHex, function (m, r, g, b) {
+ if(p.color.rgb){
+ var color_value = 'rgba('+p.color.rgb.r+','+p.color.rgb.g+','+p.color.rgb.b+','+p.opacity+')';
+ }else{
+ var color_value = 'hsla('+p.color.hsl.h+','+p.color.hsl.s+'%,'+p.color.hsl.l+'%,'+p.opacity+')';
+ }
+ return color_value;
+ });
+
+ /* prepare to create img with colored svg */
+ var svg = new Blob([coloredSvgXml], {type: 'image/svg+xml;charset=utf-8'}),
+ DOMURL = window.URL || window.webkitURL || window,
+ url = DOMURL.createObjectURL(svg);
+
+ /* create particle img obj */
+ var img = new Image();
+ img.addEventListener('load', function(){
+ p.img.obj = img;
+ p.img.loaded = true;
+ DOMURL.revokeObjectURL(url);
+ pJS.tmp.count_svg++;
+ });
+ img.src = url;
+
+ };
+
+
+ pJS.fn.vendors.destroypJS = function(){
+ cancelAnimationFrame(pJS.fn.drawAnimFrame);
+ canvas_el.remove();
+ pJSDom = null;
+ };
+
+
+ pJS.fn.vendors.drawShape = function(c, startX, startY, sideLength, sideCountNumerator, sideCountDenominator){
+
+ // By Programming Thomas - https://programmingthomas.wordpress.com/2013/04/03/n-sided-shapes/
+ var sideCount = sideCountNumerator * sideCountDenominator;
+ var decimalSides = sideCountNumerator / sideCountDenominator;
+ var interiorAngleDegrees = (180 * (decimalSides - 2)) / decimalSides;
+ var interiorAngle = Math.PI - Math.PI * interiorAngleDegrees / 180; // convert to radians
+ c.save();
+ c.beginPath();
+ c.translate(startX, startY);
+ c.moveTo(0,0);
+ for (var i = 0; i < sideCount; i++) {
+ c.lineTo(sideLength,0);
+ c.translate(sideLength,0);
+ c.rotate(interiorAngle);
+ }
+ //c.stroke();
+ c.fill();
+ c.restore();
+
+ };
+
+ pJS.fn.vendors.exportImg = function(){
+ window.open(pJS.canvas.el.toDataURL('image/png'), '_blank');
+ };
+
+
+ pJS.fn.vendors.loadImg = function(type){
+
+ pJS.tmp.img_error = undefined;
+
+ if(pJS.particles.shape.image.src != ''){
+
+ if(type == 'svg'){
+
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', pJS.particles.shape.image.src);
+ xhr.onreadystatechange = function (data) {
+ if(xhr.readyState == 4){
+ if(xhr.status == 200){
+ pJS.tmp.source_svg = data.currentTarget.response;
+ pJS.fn.vendors.checkBeforeDraw();
+ }else{
+ console.log('Error pJS - Image not found');
+ pJS.tmp.img_error = true;
+ }
+ }
+ }
+ xhr.send();
+
+ }else{
+
+ var img = new Image();
+ img.addEventListener('load', function(){
+ pJS.tmp.img_obj = img;
+ pJS.fn.vendors.checkBeforeDraw();
+ });
+ img.src = pJS.particles.shape.image.src;
+
+ }
+
+ }else{
+ console.log('Error pJS - No image.src');
+ pJS.tmp.img_error = true;
+ }
+
+ };
+
+
+ pJS.fn.vendors.draw = function(){
+
+ if(pJS.particles.shape.type == 'image'){
+
+ if(pJS.tmp.img_type == 'svg'){
+
+ if(pJS.tmp.count_svg >= pJS.particles.number.value){
+ pJS.fn.particlesDraw();
+ if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }else{
+ //console.log('still loading...');
+ if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }
+
+ }else{
+
+ if(pJS.tmp.img_obj != undefined){
+ pJS.fn.particlesDraw();
+ if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }else{
+ if(!pJS.tmp.img_error) pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }
+
+ }
+
+ }else{
+ pJS.fn.particlesDraw();
+ if(!pJS.particles.move.enable) cancelRequestAnimFrame(pJS.fn.drawAnimFrame);
+ else pJS.fn.drawAnimFrame = requestAnimFrame(pJS.fn.vendors.draw);
+ }
+
+ };
+
+
+ pJS.fn.vendors.checkBeforeDraw = function(){
+
+ // if shape is image
+ if(pJS.particles.shape.type == 'image'){
+
+ if(pJS.tmp.img_type == 'svg' && pJS.tmp.source_svg == undefined){
+ pJS.tmp.checkAnimFrame = requestAnimFrame(check);
+ }else{
+ //console.log('images loaded! cancel check');
+ cancelRequestAnimFrame(pJS.tmp.checkAnimFrame);
+ if(!pJS.tmp.img_error){
+ pJS.fn.vendors.init();
+ pJS.fn.vendors.draw();
+ }
+
+ }
+
+ }else{
+ pJS.fn.vendors.init();
+ pJS.fn.vendors.draw();
+ }
+
+ };
+
+
+ pJS.fn.vendors.init = function(){
+
+ /* init canvas + particles */
+ pJS.fn.retinaInit();
+ pJS.fn.canvasInit();
+ pJS.fn.canvasSize();
+ pJS.fn.canvasPaint();
+ pJS.fn.particlesCreate();
+ pJS.fn.vendors.densityAutoParticles();
+
+ /* particles.line_linked - convert hex colors to rgb */
+ pJS.particles.line_linked.color_rgb_line = hexToRgb(pJS.particles.line_linked.color);
+
+ };
+
+
+ pJS.fn.vendors.start = function(){
+
+ if(isInArray('image', pJS.particles.shape.type)){
+ pJS.tmp.img_type = pJS.particles.shape.image.src.substr(pJS.particles.shape.image.src.length - 3);
+ pJS.fn.vendors.loadImg(pJS.tmp.img_type);
+ }else{
+ pJS.fn.vendors.checkBeforeDraw();
+ }
+
+ };
+
+
+
+
+ /* ---------- pJS - start ------------ */
+
+
+ pJS.fn.vendors.eventsListeners();
+
+ pJS.fn.vendors.start();
+
+
+
+};
+
+/* ---------- global functions - vendors ------------ */
+
+Object.deepExtend = function(destination, source) {
+ for (var property in source) {
+ if (source[property] && source[property].constructor &&
+ source[property].constructor === Object) {
+ destination[property] = destination[property] || {};
+ arguments.callee(destination[property], source[property]);
+ } else {
+ destination[property] = source[property];
+ }
+ }
+ return destination;
+};
+
+window.requestAnimFrame = (function(){
+ return window.requestAnimationFrame ||
+ window.webkitRequestAnimationFrame ||
+ window.mozRequestAnimationFrame ||
+ window.oRequestAnimationFrame ||
+ window.msRequestAnimationFrame ||
+ function(callback){
+ window.setTimeout(callback, 1000 / 60);
+ };
+})();
+
+window.cancelRequestAnimFrame = ( function() {
+ return window.cancelAnimationFrame ||
+ window.webkitCancelRequestAnimationFrame ||
+ window.mozCancelRequestAnimationFrame ||
+ window.oCancelRequestAnimationFrame ||
+ window.msCancelRequestAnimationFrame ||
+ clearTimeout
+} )();
+
+function hexToRgb(hex){
+ // By Tim Down - https://stackoverflow.com/a/5624139/3493650
+ // Expand shorthand form (e.g. "03F") to full form (e.g. "0033FF")
+ var shorthandRegex = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
+ hex = hex.replace(shorthandRegex, function(m, r, g, b) {
+ return r + r + g + g + b + b;
+ });
+ var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
+ return result ? {
+ r: parseInt(result[1], 16),
+ g: parseInt(result[2], 16),
+ b: parseInt(result[3], 16)
+ } : null;
+};
+
+function clamp(number, min, max) {
+ return Math.min(Math.max(number, min), max);
+};
+
+function isInArray(value, array) {
+ return array.indexOf(value) > -1;
+}
+
+
+/* ---------- particles.js functions - start ------------ */
+
+window.pJSDom = [];
+
+window.particlesJS = function(tag_id, params){
+
+ //console.log(params);
+
+ /* no string id? so it's object params, and set the id with default id */
+ if(typeof(tag_id) != 'string'){
+ params = tag_id;
+ tag_id = 'particles-js';
+ }
+
+ /* no id? set the id to default id */
+ if(!tag_id){
+ tag_id = 'particles-js';
+ }
+
+ /* pJS elements */
+ var pJS_tag = document.getElementById(tag_id),
+ pJS_canvas_class = 'particles-js-canvas-el',
+ exist_canvas = pJS_tag.getElementsByClassName(pJS_canvas_class);
+
+ /* remove canvas if exists into the pJS target tag */
+ if(exist_canvas.length){
+ while(exist_canvas.length > 0){
+ pJS_tag.removeChild(exist_canvas[0]);
+ }
+ }
+
+ /* create canvas element */
+ var canvas_el = document.createElement('canvas');
+ canvas_el.className = pJS_canvas_class;
+
+ /* set size canvas */
+ canvas_el.style.width = "100%";
+ canvas_el.style.height = "100%";
+
+ /* append canvas */
+ var canvas = document.getElementById(tag_id).appendChild(canvas_el);
+
+ /* launch particle.js */
+ if(canvas != null){
+ pJSDom.push(new pJS(tag_id, params));
+ }
+
+};
+
+window.particlesJS.load = function(tag_id, path_config_json, callback){
+
+ /* load json config */
+ var xhr = new XMLHttpRequest();
+ xhr.open('GET', path_config_json);
+ xhr.onreadystatechange = function (data) {
+ if(xhr.readyState == 4){
+ if(xhr.status == 200){
+ var params = JSON.parse(data.currentTarget.response);
+ window.particlesJS(tag_id, params);
+ if(callback) callback();
+ }else{
+ console.log('Error pJS - XMLHttpRequest status: '+xhr.status);
+ console.log('Error pJS - File config not found');
+ }
+ }
+ };
+ xhr.send();
+
+};
diff --git a/docs/logos/meson.build b/docs/logos/meson.build
index 70ba67d71c..0038d4fa42 100644
--- a/docs/logos/meson.build
+++ b/docs/logos/meson.build
@@ -18,6 +18,8 @@ docs_logo_files = [
'logo-square.svg',
'logo-sticker-hexagon.svg',
'logo-sticker-square.svg',
+ 'penguin.svg',
+ 'penguin.png',
]
install_data(docs_logo_files, install_dir: docs_html_dir / 'logos')
diff --git a/docs/logos/penguin.png b/docs/logos/penguin.png
new file mode 100644
index 0000000000000000000000000000000000000000..48a481c54b6a71f2d43f5ebdf1d4455202c27d8a
GIT binary patch
literal 4236
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
literal 0
HcmV?d00001
diff --git a/docs/logos/penguin.svg b/docs/logos/penguin.svg
new file mode 100644
index 0000000000..9938dc35ab
--- /dev/null
+++ b/docs/logos/penguin.svg
@@ -0,0 +1,358 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ width="46.727402"
+ height="88.205261"
+ viewBox="0 0 12.363292 23.337642"
+ version="1.1"
+ id="svg2754"
+ inkscape:version="1.2.2 (b0a8486541, 2022-12-01)"
+ sodipodi:docname="penguin.svg"
+ inkscape:export-filename="../logo-square.png"
+ inkscape:export-xdpi="150"
+ inkscape:export-ydpi="150"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:dc="http://purl.org/dc/elements/1.1/">
+ <defs
+ id="defs2748">
+ <filter
+ style="color-interpolation-filters:sRGB"
+ inkscape:label="Drop Shadow"
+ id="filter5799-3"
+ x="-0.042427354"
+ y="-0.049351394"
+ width="1.1025327"
+ height="1.1192659">
+ <feFlood
+ flood-opacity="1"
+ flood-color="rgb(0,0,0)"
+ result="flood"
+ id="feFlood5801-7" />
+ <feComposite
+ in="flood"
+ in2="SourceGraphic"
+ operator="in"
+ result="composite1"
+ id="feComposite5803-4" />
+ <feGaussianBlur
+ in="composite1"
+ stdDeviation="6"
+ result="blur"
+ id="feGaussianBlur5805-3" />
+ <feOffset
+ dx="6"
+ dy="6"
+ result="offset"
+ id="feOffset5807-7" />
+ <feComposite
+ in="SourceGraphic"
+ in2="offset"
+ operator="over"
+ result="composite2"
+ id="feComposite5809-1" />
+ </filter>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask3913-3">
+ <path
+ style="fill:#2f6962"
+ id="path3915-9"
+ d="M 95.108,61.776 244.59,10.309 c 15.666,-5.394 32.738,2.933 38.132,18.599 l 39.799,115.58 c 5.394,15.666 -2.932,32.738 -18.598,38.131 l -103.98,35.801 z"
+ inkscape:connector-curvature="0" />
+ </mask>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask4168-6">
+ <path
+ style="fill:#7c858c"
+ id="path4170-4"
+ d="m 113.124,36.661 c 17.233,36.62 75.371,131.675 105.366,171.054 -4.069,13.505 -18.428,20.812 -30.299,17.44 L 72.849,58.555 C 72.779,46.208 95.748,31.956 113.124,36.661 Z"
+ sodipodi:nodetypes="ccccc"
+ inkscape:connector-curvature="0" />
+ </mask>
+ <filter
+ inkscape:label="Ridged Border"
+ inkscape:menu="Bevels"
+ inkscape:menu-tooltip="Ridged border with inner bevel"
+ style="color-interpolation-filters:sRGB"
+ id="filter5576-4"
+ x="0"
+ y="0"
+ width="1"
+ height="1">
+ <feMorphology
+ radius="4.3"
+ in="SourceAlpha"
+ result="result91"
+ id="feMorphology5578-9" />
+ <feComposite
+ operator="out"
+ in="SourceGraphic"
+ in2="result91"
+ id="feComposite5580-1" />
+ <feGaussianBlur
+ result="result0"
+ stdDeviation="1.2"
+ id="feGaussianBlur5582-2" />
+ <feDiffuseLighting
+ diffuseConstant="1"
+ id="feDiffuseLighting5584-3">
+ <feDistantLight
+ elevation="66"
+ azimuth="225"
+ id="feDistantLight5586-1" />
+ </feDiffuseLighting>
+ <feBlend
+ mode="multiply"
+ in2="SourceGraphic"
+ id="feBlend5588-8" />
+ <feComposite
+ operator="in"
+ in2="SourceAlpha"
+ id="feComposite5590-1" />
+ </filter>
+ <linearGradient
+ id="linearGradient3301">
+ <stop
+ id="stop3303"
+ offset="0"
+ style="stop-color:#ffffff;stop-opacity:1;" />
+ <stop
+ id="stop3305"
+ offset="1"
+ style="stop-color:#868686;stop-opacity:1;" />
+ </linearGradient>
+ <mask
+ maskUnits="userSpaceOnUse"
+ id="mask4481-9">
+ <path
+ style="clip-rule:evenodd;fill:#aaaaaa;fill-rule:evenodd"
+ id="path4483-2"
+ d="m 213.96734,236.83626 c -1.97572,1.50086 -5.71734,14.75814 -3.57441,17.84065 3.18643,4.58465 22.42412,-12.69851 20.66112,-17.24646 -1.81294,-4.67518 -15.35694,-1.41227 -17.08671,-0.59419 z m -9.6286,-7.34722 2.48938,3.78195 c 0,0 0.69017,1.04372 0.29628,3.40302 -0.6156,3.68976 -3.17495,13.25876 -3.32578,21.12255 -0.0183,0.94976 -0.91914,9.5039 7.21943,7.07006 8.1393,-2.43309 24.96824,-17.85854 28.33195,-24.69252 3.36372,-6.83399 -0.96483,-10.63865 -6.21591,-10.98709 -5.2511,-0.34921 -13.3456,0.21962 -17.06874,0.84795 -3.72313,0.62832 -3.49361,-0.75818 -6.67723,-4.3506 -0.23896,-0.26961 -5.04938,3.80468 -5.04938,3.80468 z"
+ inkscape:connector-curvature="0" />
+ </mask>
+ <filter
+ style="color-interpolation-filters:sRGB"
+ inkscape:label="Drop Shadow"
+ id="filter6162"
+ x="-0.23894344"
+ y="-0.15139444"
+ width="1.4778869"
+ height="1.3658699">
+ <feFlood
+ flood-opacity="1"
+ flood-color="rgb(0,0,0)"
+ result="flood"
+ id="feFlood6164" />
+ <feComposite
+ in="flood"
+ in2="SourceGraphic"
+ operator="in"
+ result="composite1"
+ id="feComposite6166" />
+ <feGaussianBlur
+ in="composite1"
+ stdDeviation="6"
+ result="blur"
+ id="feGaussianBlur6168" />
+ <feOffset
+ dx="6"
+ dy="6"
+ result="offset"
+ id="feOffset6170" />
+ <feComposite
+ in="SourceGraphic"
+ in2="offset"
+ operator="over"
+ result="fbSourceGraphic"
+ id="feComposite6172" />
+ <feColorMatrix
+ result="fbSourceGraphicAlpha"
+ in="fbSourceGraphic"
+ values="0 0 0 -1 0 0 0 0 -1 0 0 0 0 -1 0 0 0 0 1 0"
+ id="feColorMatrix6174" />
+ <feFlood
+ id="feFlood6176"
+ flood-opacity="1"
+ flood-color="rgb(0,0,0)"
+ result="flood"
+ in="fbSourceGraphic" />
+ <feComposite
+ id="feComposite6178"
+ in2="fbSourceGraphic"
+ in="flood"
+ operator="in"
+ result="composite1" />
+ <feGaussianBlur
+ id="feGaussianBlur6180"
+ in="composite1"
+ stdDeviation="6"
+ result="blur" />
+ <feOffset
+ id="feOffset6182"
+ dx="-6"
+ dy="6"
+ result="offset" />
+ <feComposite
+ id="feComposite6184"
+ in2="offset"
+ in="fbSourceGraphic"
+ operator="over"
+ result="composite2" />
+ </filter>
+ </defs>
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="2.5027778"
+ inkscape:cx="103.28524"
+ inkscape:cy="68.324084"
+ inkscape:document-units="mm"
+ inkscape:current-layer="g2753-0"
+ showgrid="false"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1920"
+ inkscape:window-height="1131"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
+ inkscape:window-maximized="1"
+ units="px"
+ inkscape:showpageshadow="2"
+ inkscape:pagecheckerboard="0"
+ inkscape:deskcolor="#d1d1d1" />
+ <metadata
+ id="metadata2751">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:label="Layer 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(15.314622,-233.97731)">
+ <g
+ id="g4944"
+ transform="matrix(0.24862701,-0.09049283,0.09049283,0.24862701,-92.040544,272.60195)">
+ <g
+ transform="rotate(19,545.20406,769.86173)"
+ id="g4988-0">
+ <g
+ id="g5736-0">
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ x="137.92564"
+ y="176.00142"
+ id="text5724-0"
+ transform="rotate(1.0000002)"><tspan
+ sodipodi:role="line"
+ id="tspan5726-6"
+ x="137.92564"
+ y="176.00142"
+ style="font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;font-size:180px;font-family:Overpass;-inkscape-font-specification:'Overpass Bold';letter-spacing:-10px;fill:#e6e6e6;fill-opacity:1" /></text>
+ <g
+ id="g2753-0"
+ transform="translate(-18.749067,-72.815807)">
+ <path
+ d="m 122.88954,229.92364 c 3.341,7.154 7.81,5.77 7.88,5.746 1.371,-0.472 5.829,-2.582 4.696,-5.873 -1.025,-2.977 -8.385,-3.373 -13.437,-1.633 -5.015,1.727 -10.665,6.602 -9.64,9.579 1.133,3.291 5.946,2.208 7.316,1.737 0.069,-0.024 4.799,-0.91 2.672,-9.379 -0.078,-0.312 0.404,-0.412 0.513,-0.177 z"
+ id="path2755-8"
+ style="clip-rule:evenodd;fill:#ffe600;fill-rule:evenodd"
+ inkscape:connector-curvature="0"
+ inkscape:export-filename="../penguin.png"
+ inkscape:export-xdpi="150"
+ inkscape:export-ydpi="150" />
+ <path
+ d="m 93.013543,187.02664 c -4.764,-17.913 -3.791,-32.973 2.812,-35.247 6.601997,-2.273 16.640997,8.995 23.914997,26.044 1.745,2.829 5.157,8.08 7.865,10.513 1.976,1.775 1.993,2.732 -1.079,2.212 -0.927,-0.157 -1.726,-0.358 -2.438,-0.662 5.736,19.254 5.048,35.957 -1.934,38.36 -6.981,2.404 -17.806,-10.334 -25.140997,-29.038 -0.374,0.678 -0.879,1.328 -1.513,2.022 -2.1,2.301 -2.676,1.537 -2.212,-1.079 0.636,-3.584 0.092,-9.822 -0.275,-13.125 z"
+ id="path2757-1"
+ style="fill:#000000;fill-opacity:1"
+ inkscape:connector-curvature="0" />
+ <path
+ d="m 100.36354,200.08264 c -5.497997,-15.966 -5.113997,-30.576 0.857,-32.632 5.971,-2.056 15.268,9.22 20.766,25.187 5.498,15.966 5.114,30.576 -0.857,32.632 -5.971,2.056 -15.268,-9.22 -20.766,-25.187 z m 0.699,-36.784 c -0.536,-1.558 -0.428,-3.008 0.243,-3.239 0.671,-0.231 1.649,0.845 2.186,2.402 0.536,1.558 0.427,3.008 -0.243,3.239 -0.671,0.231 -1.65,-0.845 -2.186,-2.402 z m -4.700997,1.618 c -0.536,-1.558 -0.427,-3.008 0.243,-3.239 0.67,-0.231 1.649,0.845 2.185,2.402 0.536,1.557 0.428,3.008 -0.243,3.239 -0.671,0.231 -1.649,-0.844 -2.185,-2.402 z"
+ id="path2759-9"
+ style="clip-rule:evenodd;fill:#ffffff;fill-opacity:1;fill-rule:evenodd"
+ inkscape:connector-curvature="0" />
+ <g
+ id="g2761-8"
+ transform="translate(-7.9684573,2.7456446)">
+ <ellipse
+ transform="matrix(-0.9455,0.3255,-0.3255,-0.9455,267.4128,287.6192)"
+ cx="109.643"
+ cy="166.18201"
+ rx="4.428"
+ ry="2.142"
+ id="ellipse2763-1"
+ style="fill:#ffe600" />
+ <path
+ d=""
+ id="path2765-6"
+ style="fill:#ffe600"
+ inkscape:connector-curvature="0" />
+ </g>
+ </g>
+ </g>
+ <text
+ transform="rotate(1.0000002)"
+ id="text5053-7"
+ y="53.587437"
+ x="-408.52026"
+ style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ xml:space="preserve"><tspan
+ y="53.587437"
+ x="-408.52026"
+ id="tspan5055-2"
+ sodipodi:role="line" /></text>
+ <text
+ transform="rotate(1.0000002)"
+ id="text5057-8"
+ y="-232.88652"
+ x="-525.88629"
+ style="font-style:normal;font-weight:normal;font-size:90px;line-height:125%;font-family:Sans;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ xml:space="preserve"><tspan
+ y="-232.88652"
+ x="-525.88629"
+ id="tspan5059-1"
+ sodipodi:role="line" /></text>
+ <text
+ transform="rotate(1.0000002)"
+ id="text5069-7"
+ y="-200.07454"
+ x="543.02759"
+ style="font-style:normal;font-weight:normal;font-size:40px;line-height:125%;font-family:Sans;text-align:start;letter-spacing:0px;word-spacing:0px;text-anchor:start;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ xml:space="preserve"><tspan
+ y="-200.07454"
+ x="543.02759"
+ id="tspan5071-7"
+ sodipodi:role="line" /></text>
+ </g>
+ <text
+ xml:space="preserve"
+ style="font-style:normal;font-weight:normal;font-size:40px;line-height:25px;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ x="582.63574"
+ y="-37.070248"
+ id="text4950"><tspan
+ sodipodi:role="line"
+ id="tspan4948"
+ x="582.63574"
+ y="-37.070248" /></text>
+ </g>
+ </g>
+</svg>
diff --git a/docs/page.xsl b/docs/page.xsl
index 548d5a11c4..7c4f295053 100644
--- a/docs/page.xsl
+++ b/docs/page.xsl
@@ -116,6 +116,9 @@
<script type="text/javascript" src="{$href_base}js/main.js">
<xsl:comment>// forces non-empty element</xsl:comment>
</script>
+ <script type="text/javascript" src="{$href_base}js/particles.js">
+ <xsl:comment>// forces non-empty element</xsl:comment>
+ </script>
</head>
<body onload="pageload()">
<div id="body">
@@ -197,6 +200,11 @@
</div>
<br class="clear"/>
</div>
+ <xsl:if test="$pagesrc = 'docs/404.html.in'">
+ <script src="{$href_base}js/app.js">
+ <xsl:comment>// forces non-empty element</xsl:comment>
+ </script>
+ </xsl:if>
</body>
</html>
</xsl:template>
--
2.39.1
4
4
The following changes since commit 6a50f64ca01d0a7b97f14f069762bfd88160f31e:
Merge tag 'pull-request-2023-02-14' of https://gitlab.com/thuth/qemu into staging (2023-02-14 14:46:10 +0000)
are available in the Git repository at:
https://gitlab.com/berrange/qemu tags/misc-next-pull-request
for you to fetch changes up to 36debafddd788066be10b33c5f11b984a08e5c85:
ui: remove deprecated 'password' option for SPICE (2023-02-15 11:14:58 -0500)
----------------------------------------------------------------
* Document 'password-secret' option for -iscsi
* Deprecate iSCSI 'password' in favour of 'password-secret'
* Remove deprecated 'password' option for SPICE
* Fix handling of cached read buffers with TLS
----------------------------------------------------------------
Antoine Damhet (2):
crypto: TLS: introduce `check_pending`
io/channel-tls: fix handling of bigger read buffers
Daniel P. Berrangé (3):
block: mention 'password-secret' option for -iscsi
block: deprecate iSCSI 'password' in favour of 'password-secret'
ui: remove deprecated 'password' option for SPICE
block/iscsi.c | 3 ++
crypto/tlssession.c | 14 +++++++
docs/about/deprecated.rst | 16 ++++----
docs/about/removed-features.rst | 7 ++++
include/crypto/tlssession.h | 11 ++++++
io/channel-tls.c | 66 ++++++++++++++++++++++++++++++++-
qemu-options.hx | 13 ++-----
ui/spice-core.c | 15 --------
8 files changed, 111 insertions(+), 34 deletions(-)
--
2.39.1
2
6
Here are some cleanup, as promised here:
https://listman.redhat.com/archives/libvir-list/2023-February/237721.html
Now, there are still some patches missing.
Firstly, we still don't really capture error from passt. My suggestion
was to wait for socket to show up with errfd open. But active wait is
viewed as undesirable [1].
Secondly, Laine reported SELinux issues. Yeah, I don't see us setting
SELinux label on nor socket that passt and QEMU talk to each other, nor
on the log file. Speaking of which - we usually have per domain (or per
helper daemon instance even) log file, while for passt we have a global
one (/var/log/passt.log). I don't think that will fly if two or more
SELinux enabled domains want to use passt.
Thirdly, Stefano suggested a graceful shutdown for passt: have libvirt
connect to the socket and close it. Since we pass --one-off, this should
singal passt to exit. But I haven't implemented that because it's
redundant. We can't rely on passt quitting itself and thus use the big
gun (virPidFileForceCleanupPath()) at which point, the socket way is
just an optimization.
I might look into the first two, at some point. But not today.
1: https://listman.redhat.com/archives/libvir-list/2023-February/237663.html
Michal Prívozník (4):
Revert "qemu: allow passt to self-daemonize"
qemu_extdevice: Make qemuExtDevicesHasDevice() check def->nets
qemu_passt: Report error when getting passt PID failed
qemu_passt: Don't let passt fork off
src/qemu/qemu_extdevice.c | 11 +++++++++++
src/qemu/qemu_passt.c | 15 ++++++++++-----
2 files changed, 21 insertions(+), 5 deletions(-)
--
2.39.1
5
18
[PATCH v4 14/16] qapi: deprecate "device" field of DEVICE_* events
by Vladimir Sementsov-Ogievskiy 16 Feb '23
by Vladimir Sementsov-Ogievskiy 16 Feb '23
16 Feb '23
The device field is redundant, because QOM path always include device
ID when this ID exist.
Signed-off-by: Vladimir Sementsov-Ogievskiy <vsementsov(a)yandex-team.ru>
---
docs/about/deprecated.rst | 9 +++++++++
qapi/qdev.json | 12 ++++++++++--
2 files changed, 19 insertions(+), 2 deletions(-)
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index da2e6fe63d..b389934691 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -171,6 +171,15 @@ accepted incorrect commands will return an error. Users should make sure that
all arguments passed to ``device_add`` are consistent with the documented
property types.
+QEMU Machine Protocol (QMP) events
+----------------------------------
+
+``DEVICE_DELETED`` & ``DEVICE_UNPLUG_GUEST_ERROR`` field ``device`` (since 8.0)
+'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
+
+Devices that has ``ID`` always has QOM path `/machine/peripheral/ID`. So, the
+``device`` field is redundant and deprecated. Use the ``path`` field instead.
+
Host Architectures
------------------
diff --git a/qapi/qdev.json b/qapi/qdev.json
index 2708fb4e99..325ef554f9 100644
--- a/qapi/qdev.json
+++ b/qapi/qdev.json
@@ -124,6 +124,9 @@
#
# @path: the device's QOM path
#
+# Features:
+# @deprecated: Member @device is deprecated as redundant. Use @path instead.
+#
# Since: 1.5
#
# Example:
@@ -135,7 +138,8 @@
#
##
{ 'event': 'DEVICE_DELETED',
- 'data': { '*device': 'str', 'path': 'str' } }
+ 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] },
+ 'path': 'str' } }
##
# @DEVICE_UNPLUG_GUEST_ERROR:
@@ -146,6 +150,9 @@
#
# @path: the device's QOM path
#
+# Features:
+# @deprecated: Member @device is deprecated as redundant. Use @path instead.
+#
# Since: 6.2
#
# Example:
@@ -157,4 +164,5 @@
#
##
{ 'event': 'DEVICE_UNPLUG_GUEST_ERROR',
- 'data': { '*device': 'str', 'path': 'str' } }
+ 'data': { '*device': { 'type': 'str', 'features': [ 'deprecated' ] },
+ 'path': 'str' } }
--
2.34.1
5
17
[PATCH] qemu_extdevice: Add a comment into qemuExtDevicesSetupCgroup()
by Michal Privoznik 15 Feb '23
by Michal Privoznik 15 Feb '23
15 Feb '23
The way setting up CGroups for external helpers work, is:
qemuExtDevicesHasDevice() is called first to determine whether
there is a helper process running, the CGroup controller is
created and then qemuExtDevicesSetupCgroup() is called to place
helpers into the CGroup. But when one reads just
qemuExtDevicesSetupCgroup() it's easy to miss this hidden logic.
Therefore, add a warning at the beginning of the function.
Signed-off-by: Michal Privoznik <mprivozn(a)redhat.com>
---
src/qemu/qemu_extdevice.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/qemu/qemu_extdevice.c b/src/qemu/qemu_extdevice.c
index 47e97f3565..1c397972e4 100644
--- a/src/qemu/qemu_extdevice.c
+++ b/src/qemu/qemu_extdevice.c
@@ -331,6 +331,9 @@ qemuExtDevicesSetupCgroup(virQEMUDriver *driver,
virDomainDef *def = vm->def;
size_t i;
+ /* Don't forget to adjust qemuExtDevicesHasDevice() accordingly.
+ * Otherwise, this function might not be called at all. */
+
if (qemuDBusSetupCgroup(driver, vm, cgroup) < 0)
return -1;
--
2.39.1
2
1
https://gitlab.com/libvirt/libvirt-wiki/-/merge_requests/1
Hi,
in order to ease editing of the libvirt wiki, remove the need for
registering users and remove the need to run PHP in an openshift instance
I've decided to contents of the libvirt wiki into a staticaly generated
page using (almost) the same approach we use to generate the libvirt web
pages from rST documents in the repo.
All articles were converted into rST files [1] and images linked from
currently existing articles were dowloaded.
Advantages:
- same workflow as with editing the libvirt pages
- gitlab still provides a web editor
- local editing for users who hate web
- no need to deal with user registration
- no need to run PHP in openshift
- we still keep separate space for docs which don't really belong into the
main repo
- even if we decide to kill-off the wiki eventually the valuable content
will be easier to port to the kbase as it'll be in rST
- the conversion fixed many orphaned pages
Disadvantages:
- all links will be broken [2]
- changes will need to be reviewed/approved
- low quality/obsolete content is forward-ported as I didn't review
anything
- the build script is in bash (This obviously can be changed if somebody
cares more than I do.)
The generator is based on a cleaned up page.xsl and other assets from
libvirt's repo and the check-html-references script [3] to validate linking.
The new wiki can for now be browsed from artifacts of the pipeline job that
I've used to test it:
https://pipo.sk.gitlab.io/-/libvirt-wiki/-/jobs/3771076975/artifacts/websit…
(I know my username is unfortunate to contain a dot which breaks the
certificate)
If somebody wishes to see the extremely ugly conversion scripts:
https://gitlab.com/pipo.sk/libvirt-wiki/-/commit/fe36e37d3580a76ca18e512354…
[1] The conversion was done using a collection of ugly scripts and pandoc.
Unfortunately markdown-eque formats have the issue of not really having
strict rules and in certain cases the tools used to process them not
implementing them correctly. This meant that the least painful was actually
the coversion from HTML!!! and not the internal mediawiki format.
[2] If we really want to preserve links I can modify the script to generate
a list of redirects for the webserver, but I really doubt that preserving
links has value. Additionally some content was moved to the knowledge base,
so I really want to just delete it from the wiki, so breaking links is a
feature.
[3] It uses the version after the last patchset:
https://listman.redhat.com/archives/libvir-list/2023-February/237785.html
2
4
Improve the checker tool to also track orphaned pages and check presence
and usage of images. In addition to that this series fixes handful of
instances of the problems that the script caught.
This series adds two documents:
- docs/logos/README.rst (converted into docs/logos/index.html)
The page shows all logos which libvirt has. It's now linked from the
docs page.
https://pipo.sk.gitlab.io/-/libvirt/-/jobs/3770134533/artifacts/website/log…
- docs/golang.rst
The page ties together the 4 go module pages we have which were not
linked and is linked from docs.html
https://pipo.sk.gitlab.io/-/libvirt/-/jobs/3770134533/artifacts/website/gol…
Peter Krempa (9):
docs: XSL: Add source document name as custom data attribute for
<html>
scripts: check-html-references: Rename --prefix to --webroot and make
it mandatory
scripts: check-html-references: Improve error messages and don't mess
with relative paths
docs: manpages: Add missing manpages to index
docs: Add sub-page for all golang modules
scripts: check-html-references: Detect pages that are not linked to
kbase: eventloop: Fix path to referenced images
docs: logos: Turn 'README' into rST, generate an index and link to
images
scripts: check-html-refernces: Add checking for image file usage
docs/docs.rst | 5 +-
docs/golang.rst | 21 +++
docs/kbase/internals/eventloop.rst | 4 +-
docs/logos/README | 98 --------------
docs/logos/README.rst | 166 ++++++++++++++++++++++++
docs/logos/meson.build | 47 +++++++
docs/manpages/index.rst | 3 +
docs/meson.build | 3 +-
docs/page.xsl | 2 +-
scripts/check-html-references.py | 198 +++++++++++++++++++++++------
10 files changed, 406 insertions(+), 141 deletions(-)
create mode 100644 docs/golang.rst
delete mode 100644 docs/logos/README
create mode 100644 docs/logos/README.rst
--
2.39.1
2
18
Please see individual patches for justification.
Peter Krempa (3):
rpc: client: Don't check return value of virNetMessageNew
rpc: Don't warn about "max_client_requests" in single-threaded daemons
virLogCleanerShutdown: Don't call g_regex_unref on NULL regex
src/logging/log_cleaner.c | 3 +--
src/remote/libvirtd.conf.in | 1 +
src/rpc/virnetserverclient.c | 14 ++++++--------
3 files changed, 8 insertions(+), 10 deletions(-)
--
2.39.1
2
6
Hello,
I don't know if this is the right email list for this question, let me try.
I experienced a problem when I want to assign PCIe VF to my VMs, I can
use "lspci" to list the VF PCIe, even PF PCIe, but the command " virsh
nodedev-list"
doesn't print any PCIe bus device. I tried using "virsh edit --domain "
command and added the PCIe bus to the XML file, but when I start the VM,
the error message
shows an internal error, there is an invalid link to the device.
Meanwhile, I use virt-manager to see if I can add a PCIe host device,
but the host device shows "no device available".
my system is ARM64 based Nvidia platform, I have enabled IOMMU in the
kernel. do you know how can I figure out the root cause? is this the
ARM64 kernel issue or something else??
I posted this issue also in Nvidia forum:
https://forums.developer.nvidia.com/t/nvidia-orin-pcie-device-there-is-no-p…
thanks so much for your suggestions.
Martin
1
0