Merge pull request #5863 from fredj/stroke_pattern
Allow CanvasPattern or CanvasGradient as stroke style
This commit is contained in:
@@ -6932,7 +6932,7 @@ olx.style.RegularShapeOptions.prototype.atlasManager;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {{color: (ol.Color|string|undefined),
|
* @typedef {{color: (ol.Color|ol.ColorLike|undefined),
|
||||||
* lineCap: (string|undefined),
|
* lineCap: (string|undefined),
|
||||||
* lineJoin: (string|undefined),
|
* lineJoin: (string|undefined),
|
||||||
* lineDash: (Array.<number>|undefined),
|
* lineDash: (Array.<number>|undefined),
|
||||||
@@ -6943,9 +6943,10 @@ olx.style.StrokeOptions;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Color. See {@link ol.color} for possible formats. Default null; if null,
|
* A color, gradient or pattern. See {@link ol.color}
|
||||||
* the Canvas/renderer default black will be used.
|
* and {@link ol.colorlike} for possible formats. Default null;
|
||||||
* @type {ol.Color|string|undefined}
|
* if null, the Canvas/renderer default black will be used.
|
||||||
|
* @type {ol.Color|ol.ColorLike|undefined}
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
olx.style.StrokeOptions.prototype.color;
|
olx.style.StrokeOptions.prototype.color;
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ goog.provide('ol.render.canvas.Immediate');
|
|||||||
|
|
||||||
goog.require('ol');
|
goog.require('ol');
|
||||||
goog.require('ol.array');
|
goog.require('ol.array');
|
||||||
goog.require('ol.color');
|
|
||||||
goog.require('ol.colorlike');
|
goog.require('ol.colorlike');
|
||||||
goog.require('ol.extent');
|
goog.require('ol.extent');
|
||||||
goog.require('ol.geom.GeometryType');
|
goog.require('ol.geom.GeometryType');
|
||||||
@@ -841,7 +840,7 @@ ol.render.canvas.Immediate.prototype.setFillStrokeStyle = function(fillStyle, st
|
|||||||
strokeStyleWidth : ol.render.canvas.defaultLineWidth),
|
strokeStyleWidth : ol.render.canvas.defaultLineWidth),
|
||||||
miterLimit: strokeStyleMiterLimit !== undefined ?
|
miterLimit: strokeStyleMiterLimit !== undefined ?
|
||||||
strokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit,
|
strokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit,
|
||||||
strokeStyle: ol.color.asString(strokeStyleColor ?
|
strokeStyle: ol.colorlike.asColorLike(strokeStyleColor ?
|
||||||
strokeStyleColor : ol.render.canvas.defaultStrokeStyle)
|
strokeStyleColor : ol.render.canvas.defaultStrokeStyle)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -921,7 +920,7 @@ ol.render.canvas.Immediate.prototype.setTextStyle = function(textStyle) {
|
|||||||
textStrokeStyleWidth : ol.render.canvas.defaultLineWidth,
|
textStrokeStyleWidth : ol.render.canvas.defaultLineWidth,
|
||||||
miterLimit: textStrokeStyleMiterLimit !== undefined ?
|
miterLimit: textStrokeStyleMiterLimit !== undefined ?
|
||||||
textStrokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit,
|
textStrokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit,
|
||||||
strokeStyle: ol.color.asString(textStrokeStyleColor ?
|
strokeStyle: ol.colorlike.asColorLike(textStrokeStyleColor ?
|
||||||
textStrokeStyleColor : ol.render.canvas.defaultStrokeStyle)
|
textStrokeStyleColor : ol.render.canvas.defaultStrokeStyle)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ goog.provide('ol.render.canvas.LineStringReplay');
|
|||||||
|
|
||||||
goog.require('ol');
|
goog.require('ol');
|
||||||
goog.require('ol.array');
|
goog.require('ol.array');
|
||||||
goog.require('ol.color');
|
goog.require('ol.colorlike');
|
||||||
goog.require('ol.extent');
|
goog.require('ol.extent');
|
||||||
goog.require('ol.render.canvas');
|
goog.require('ol.render.canvas');
|
||||||
goog.require('ol.render.canvas.Instruction');
|
goog.require('ol.render.canvas.Instruction');
|
||||||
@@ -30,14 +30,14 @@ ol.render.canvas.LineStringReplay = function(tolerance, maxExtent, resolution, o
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {{currentStrokeStyle: (string|undefined),
|
* @type {{currentStrokeStyle: (ol.ColorLike|undefined),
|
||||||
* currentLineCap: (string|undefined),
|
* currentLineCap: (string|undefined),
|
||||||
* currentLineDash: Array.<number>,
|
* currentLineDash: Array.<number>,
|
||||||
* currentLineJoin: (string|undefined),
|
* currentLineJoin: (string|undefined),
|
||||||
* currentLineWidth: (number|undefined),
|
* currentLineWidth: (number|undefined),
|
||||||
* currentMiterLimit: (number|undefined),
|
* currentMiterLimit: (number|undefined),
|
||||||
* lastStroke: number,
|
* lastStroke: number,
|
||||||
* strokeStyle: (string|undefined),
|
* strokeStyle: (ol.ColorLike|undefined),
|
||||||
* lineCap: (string|undefined),
|
* lineCap: (string|undefined),
|
||||||
* lineDash: Array.<number>,
|
* lineDash: Array.<number>,
|
||||||
* lineJoin: (string|undefined),
|
* lineJoin: (string|undefined),
|
||||||
@@ -223,7 +223,7 @@ ol.render.canvas.LineStringReplay.prototype.setFillStrokeStyle = function(fillSt
|
|||||||
ol.DEBUG && console.assert(!fillStyle, 'fillStyle should be null');
|
ol.DEBUG && console.assert(!fillStyle, 'fillStyle should be null');
|
||||||
ol.DEBUG && console.assert(strokeStyle, 'strokeStyle should not be null');
|
ol.DEBUG && console.assert(strokeStyle, 'strokeStyle should not be null');
|
||||||
var strokeStyleColor = strokeStyle.getColor();
|
var strokeStyleColor = strokeStyle.getColor();
|
||||||
this.state_.strokeStyle = ol.color.asString(strokeStyleColor ?
|
this.state_.strokeStyle = ol.colorlike.asColorLike(strokeStyleColor ?
|
||||||
strokeStyleColor : ol.render.canvas.defaultStrokeStyle);
|
strokeStyleColor : ol.render.canvas.defaultStrokeStyle);
|
||||||
var strokeStyleLineCap = strokeStyle.getLineCap();
|
var strokeStyleLineCap = strokeStyle.getLineCap();
|
||||||
this.state_.lineCap = strokeStyleLineCap !== undefined ?
|
this.state_.lineCap = strokeStyleLineCap !== undefined ?
|
||||||
|
|||||||
@@ -32,14 +32,14 @@ ol.render.canvas.PolygonReplay = function(tolerance, maxExtent, resolution, over
|
|||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {{currentFillStyle: (ol.ColorLike|undefined),
|
* @type {{currentFillStyle: (ol.ColorLike|undefined),
|
||||||
* currentStrokeStyle: (string|undefined),
|
* currentStrokeStyle: (ol.ColorLike|undefined),
|
||||||
* currentLineCap: (string|undefined),
|
* currentLineCap: (string|undefined),
|
||||||
* currentLineDash: Array.<number>,
|
* currentLineDash: Array.<number>,
|
||||||
* currentLineJoin: (string|undefined),
|
* currentLineJoin: (string|undefined),
|
||||||
* currentLineWidth: (number|undefined),
|
* currentLineWidth: (number|undefined),
|
||||||
* currentMiterLimit: (number|undefined),
|
* currentMiterLimit: (number|undefined),
|
||||||
* fillStyle: (ol.ColorLike|undefined),
|
* fillStyle: (ol.ColorLike|undefined),
|
||||||
* strokeStyle: (string|undefined),
|
* strokeStyle: (ol.ColorLike|undefined),
|
||||||
* lineCap: (string|undefined),
|
* lineCap: (string|undefined),
|
||||||
* lineDash: Array.<number>,
|
* lineDash: Array.<number>,
|
||||||
* lineJoin: (string|undefined),
|
* lineJoin: (string|undefined),
|
||||||
@@ -296,7 +296,7 @@ ol.render.canvas.PolygonReplay.prototype.setFillStrokeStyle = function(fillStyle
|
|||||||
}
|
}
|
||||||
if (strokeStyle) {
|
if (strokeStyle) {
|
||||||
var strokeStyleColor = strokeStyle.getColor();
|
var strokeStyleColor = strokeStyle.getColor();
|
||||||
state.strokeStyle = ol.color.asString(strokeStyleColor ?
|
state.strokeStyle = ol.colorlike.asColorLike(strokeStyleColor ?
|
||||||
strokeStyleColor : ol.render.canvas.defaultStrokeStyle);
|
strokeStyleColor : ol.render.canvas.defaultStrokeStyle);
|
||||||
var strokeStyleLineCap = strokeStyle.getLineCap();
|
var strokeStyleLineCap = strokeStyle.getLineCap();
|
||||||
state.lineCap = strokeStyleLineCap !== undefined ?
|
state.lineCap = strokeStyleLineCap !== undefined ?
|
||||||
|
|||||||
@@ -476,8 +476,8 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
|||||||
++i;
|
++i;
|
||||||
break;
|
break;
|
||||||
case ol.render.canvas.Instruction.SET_STROKE_STYLE:
|
case ol.render.canvas.Instruction.SET_STROKE_STYLE:
|
||||||
ol.DEBUG && console.assert(typeof instruction[1] === 'string',
|
ol.DEBUG && console.assert(ol.colorlike.isColorLike(instruction[1]),
|
||||||
'2nd instruction should be a string');
|
'2nd instruction should be a string, CanvasPattern, or CanvasGradient');
|
||||||
ol.DEBUG && console.assert(typeof instruction[2] === 'number',
|
ol.DEBUG && console.assert(typeof instruction[2] === 'number',
|
||||||
'3rd instruction should be a number');
|
'3rd instruction should be a number');
|
||||||
ol.DEBUG && console.assert(typeof instruction[3] === 'string',
|
ol.DEBUG && console.assert(typeof instruction[3] === 'string',
|
||||||
@@ -495,7 +495,7 @@ ol.render.canvas.Replay.prototype.replay_ = function(
|
|||||||
context.stroke();
|
context.stroke();
|
||||||
pendingStroke = 0;
|
pendingStroke = 0;
|
||||||
}
|
}
|
||||||
context.strokeStyle = /** @type {string} */ (instruction[1]);
|
context.strokeStyle = /** @type {ol.ColorLike} */ (instruction[1]);
|
||||||
context.lineWidth = usePixelRatio ? lineWidth * pixelRatio : lineWidth;
|
context.lineWidth = usePixelRatio ? lineWidth * pixelRatio : lineWidth;
|
||||||
context.lineCap = /** @type {string} */ (instruction[3]);
|
context.lineCap = /** @type {string} */ (instruction[3]);
|
||||||
context.lineJoin = /** @type {string} */ (instruction[4]);
|
context.lineJoin = /** @type {string} */ (instruction[4]);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
goog.provide('ol.render.canvas.TextReplay');
|
goog.provide('ol.render.canvas.TextReplay');
|
||||||
|
|
||||||
goog.require('ol');
|
goog.require('ol');
|
||||||
goog.require('ol.color');
|
|
||||||
goog.require('ol.colorlike');
|
goog.require('ol.colorlike');
|
||||||
goog.require('ol.render.canvas');
|
goog.require('ol.render.canvas');
|
||||||
goog.require('ol.render.canvas.Instruction');
|
goog.require('ol.render.canvas.Instruction');
|
||||||
@@ -267,7 +266,7 @@ ol.render.canvas.TextReplay.prototype.setTextStyle = function(textStyle) {
|
|||||||
textStrokeStyleWidth : ol.render.canvas.defaultLineWidth;
|
textStrokeStyleWidth : ol.render.canvas.defaultLineWidth;
|
||||||
var miterLimit = textStrokeStyleMiterLimit !== undefined ?
|
var miterLimit = textStrokeStyleMiterLimit !== undefined ?
|
||||||
textStrokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit;
|
textStrokeStyleMiterLimit : ol.render.canvas.defaultMiterLimit;
|
||||||
var strokeStyle = ol.color.asString(textStrokeStyleColor ?
|
var strokeStyle = ol.colorlike.asColorLike(textStrokeStyleColor ?
|
||||||
textStrokeStyleColor : ol.render.canvas.defaultStrokeStyle);
|
textStrokeStyleColor : ol.render.canvas.defaultStrokeStyle);
|
||||||
if (!this.textStrokeState_) {
|
if (!this.textStrokeState_) {
|
||||||
this.textStrokeState_ = {
|
this.textStrokeState_ = {
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ ol.style.Circle.prototype.render_ = function(atlasManager) {
|
|||||||
var strokeWidth = 0;
|
var strokeWidth = 0;
|
||||||
|
|
||||||
if (this.stroke_) {
|
if (this.stroke_) {
|
||||||
strokeStyle = ol.color.asString(this.stroke_.getColor());
|
strokeStyle = ol.colorlike.asColorLike(this.stroke_.getColor());
|
||||||
strokeWidth = this.stroke_.getWidth();
|
strokeWidth = this.stroke_.getWidth();
|
||||||
if (strokeWidth === undefined) {
|
if (strokeWidth === undefined) {
|
||||||
strokeWidth = ol.render.canvas.defaultLineWidth;
|
strokeWidth = ol.render.canvas.defaultLineWidth;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
goog.provide('ol.style.RegularShape');
|
goog.provide('ol.style.RegularShape');
|
||||||
|
|
||||||
goog.require('ol');
|
goog.require('ol');
|
||||||
goog.require('ol.color');
|
|
||||||
goog.require('ol.colorlike');
|
goog.require('ol.colorlike');
|
||||||
goog.require('ol.dom');
|
goog.require('ol.dom');
|
||||||
goog.require('ol.has');
|
goog.require('ol.has');
|
||||||
@@ -329,7 +328,7 @@ ol.style.RegularShape.prototype.render_ = function(atlasManager) {
|
|||||||
var strokeWidth = 0;
|
var strokeWidth = 0;
|
||||||
|
|
||||||
if (this.stroke_) {
|
if (this.stroke_) {
|
||||||
strokeStyle = ol.color.asString(this.stroke_.getColor());
|
strokeStyle = ol.colorlike.asColorLike(this.stroke_.getColor());
|
||||||
strokeWidth = this.stroke_.getWidth();
|
strokeWidth = this.stroke_.getWidth();
|
||||||
if (strokeWidth === undefined) {
|
if (strokeWidth === undefined) {
|
||||||
strokeWidth = ol.render.canvas.defaultLineWidth;
|
strokeWidth = ol.render.canvas.defaultLineWidth;
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
goog.provide('ol.style.Stroke');
|
goog.provide('ol.style.Stroke');
|
||||||
|
|
||||||
goog.require('ol.color');
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @classdesc
|
* @classdesc
|
||||||
@@ -20,7 +18,7 @@ ol.style.Stroke = function(opt_options) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* @type {ol.Color|string}
|
* @type {ol.Color|ol.ColorLike}
|
||||||
*/
|
*/
|
||||||
this.color_ = options.color !== undefined ? options.color : null;
|
this.color_ = options.color !== undefined ? options.color : null;
|
||||||
|
|
||||||
@@ -82,7 +80,7 @@ ol.style.Stroke.prototype.clone = function() {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the stroke color.
|
* Get the stroke color.
|
||||||
* @return {ol.Color|string} Color.
|
* @return {ol.Color|ol.ColorLike} Color.
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
ol.style.Stroke.prototype.getColor = function() {
|
ol.style.Stroke.prototype.getColor = function() {
|
||||||
@@ -143,7 +141,7 @@ ol.style.Stroke.prototype.getWidth = function() {
|
|||||||
/**
|
/**
|
||||||
* Set the color.
|
* Set the color.
|
||||||
*
|
*
|
||||||
* @param {ol.Color|string} color Color.
|
* @param {ol.Color|ol.ColorLike} color Color.
|
||||||
* @api
|
* @api
|
||||||
*/
|
*/
|
||||||
ol.style.Stroke.prototype.setColor = function(color) {
|
ol.style.Stroke.prototype.setColor = function(color) {
|
||||||
@@ -223,9 +221,17 @@ ol.style.Stroke.prototype.setWidth = function(width) {
|
|||||||
*/
|
*/
|
||||||
ol.style.Stroke.prototype.getChecksum = function() {
|
ol.style.Stroke.prototype.getChecksum = function() {
|
||||||
if (this.checksum_ === undefined) {
|
if (this.checksum_ === undefined) {
|
||||||
this.checksum_ = 's' +
|
this.checksum_ = 's';
|
||||||
(this.color_ ?
|
if (this.color_) {
|
||||||
ol.color.asString(this.color_) : '-') + ',' +
|
if (typeof this.color_ === 'string') {
|
||||||
|
this.checksum_ += this.color_;
|
||||||
|
} else {
|
||||||
|
this.checksum_ += ol.getUid(this.color_).toString();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.checksum_ += '-';
|
||||||
|
}
|
||||||
|
this.checksum_ += ',' +
|
||||||
(this.lineCap_ !== undefined ?
|
(this.lineCap_ !== undefined ?
|
||||||
this.lineCap_.toString() : '-') + ',' +
|
this.lineCap_.toString() : '-') + ',' +
|
||||||
(this.lineDash_ ?
|
(this.lineDash_ ?
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ ol.CanvasFunctionType;
|
|||||||
* lineJoin: string,
|
* lineJoin: string,
|
||||||
* lineWidth: number,
|
* lineWidth: number,
|
||||||
* miterLimit: number,
|
* miterLimit: number,
|
||||||
* strokeStyle: string}}
|
* strokeStyle: ol.ColorLike}}
|
||||||
*/
|
*/
|
||||||
ol.CanvasStrokeState;
|
ol.CanvasStrokeState;
|
||||||
|
|
||||||
@@ -95,7 +95,7 @@ ol.CenterConstraintType;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {{strokeStyle: (string|undefined), strokeWidth: number,
|
* @typedef {{strokeStyle: (ol.ColorLike|undefined), strokeWidth: number,
|
||||||
* size: number, lineDash: Array.<number>}}
|
* size: number, lineDash: Array.<number>}}
|
||||||
*/
|
*/
|
||||||
ol.CircleRenderOptions;
|
ol.CircleRenderOptions;
|
||||||
@@ -112,7 +112,8 @@ ol.Color;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A type accepted by CanvasRenderingContext2D.fillStyle.
|
* A type accepted by CanvasRenderingContext2D.fillStyle
|
||||||
|
* or CanvasRenderingContext2D.strokeStyle.
|
||||||
* Represents a color, pattern, or gradient.
|
* Represents a color, pattern, or gradient.
|
||||||
*
|
*
|
||||||
* @typedef {string|CanvasPattern|CanvasGradient}
|
* @typedef {string|CanvasPattern|CanvasGradient}
|
||||||
@@ -405,7 +406,7 @@ ol.RasterOperation;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @typedef {{
|
* @typedef {{
|
||||||
* strokeStyle: (string|undefined),
|
* strokeStyle: (ol.ColorLike|undefined),
|
||||||
* strokeWidth: number,
|
* strokeWidth: number,
|
||||||
* size: number,
|
* size: number,
|
||||||
* lineCap: string,
|
* lineCap: string,
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 1.5 KiB |
@@ -260,4 +260,62 @@ describe('ol.rendering.style.Polygon', function() {
|
|||||||
IMAGE_TOLERANCE, done);
|
IMAGE_TOLERANCE, done);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('CanvasPattern and LinearGradient as fills and strokes', function() {
|
||||||
|
afterEach(function() {
|
||||||
|
disposeMap(map);
|
||||||
|
});
|
||||||
|
|
||||||
|
function createRainbowGradient() {
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
var context = canvas.getContext('2d');
|
||||||
|
var gradient = context.createLinearGradient(0,0,30,0);
|
||||||
|
gradient.addColorStop(0, 'red');
|
||||||
|
gradient.addColorStop(1 / 6, 'orange');
|
||||||
|
gradient.addColorStop(2 / 6, 'yellow');
|
||||||
|
gradient.addColorStop(3 / 6, 'green');
|
||||||
|
gradient.addColorStop(4 / 6, 'aqua');
|
||||||
|
gradient.addColorStop(5 / 6, 'blue');
|
||||||
|
gradient.addColorStop(1, 'purple');
|
||||||
|
return gradient;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createPattern() {
|
||||||
|
var canvas = document.createElement('canvas');
|
||||||
|
var context = canvas.getContext('2d');
|
||||||
|
canvas.width = 11;
|
||||||
|
canvas.height = 11;
|
||||||
|
context.fillStyle = 'rgba(102, 0, 102, 0.5)';
|
||||||
|
context.beginPath();
|
||||||
|
context.arc(5, 5, 4, 0, 2 * Math.PI);
|
||||||
|
context.fill();
|
||||||
|
context.fillStyle = 'rgb(55, 0, 170)';
|
||||||
|
context.beginPath();
|
||||||
|
context.arc(5, 5, 2, 0, 2 * Math.PI);
|
||||||
|
context.fill();
|
||||||
|
return context.createPattern(canvas, 'repeat');
|
||||||
|
}
|
||||||
|
|
||||||
|
function createFeatures() {
|
||||||
|
var feature = new ol.Feature({
|
||||||
|
geometry: new ol.geom.Polygon([
|
||||||
|
[[-20, -20], [-20, 20], [18, 20], [-20, -20]]
|
||||||
|
])
|
||||||
|
});
|
||||||
|
feature.setStyle(new ol.style.Style({
|
||||||
|
fill: new ol.style.Fill({color: createPattern()}),
|
||||||
|
stroke: new ol.style.Stroke({color: createRainbowGradient(), width: 3})
|
||||||
|
}));
|
||||||
|
vectorSource.addFeature(feature);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('tests the canvas renderer', function(done) {
|
||||||
|
map = createMap('canvas');
|
||||||
|
createFeatures();
|
||||||
|
expectResemble(
|
||||||
|
map, 'spec/ol/style/expected/polygon-pattern-gradient-canvas.png',
|
||||||
|
2.75, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user