add "file-rule" drawing element attribute
This commit is contained in:
parent
9bde4d3013
commit
04894a9031
|
|
@ -9,6 +9,8 @@
|
|||
* 0 : miter, 1 : round, 2 : bevel
|
||||
* line-cap (no string):
|
||||
* 0 : butt, 1 : round, 2 : square
|
||||
* fill-rule (no string):
|
||||
* 0 : nonzero (winding in Cairo), 1 : evenodd
|
||||
*
|
||||
* dash:
|
||||
* dash-array-on is the length of dashes (no dashes if 0, you can put 0.1 to get dots or square according to line-cap).
|
||||
|
|
@ -33,6 +35,7 @@
|
|||
-drawing-line-width: 5px;
|
||||
-drawing-line-join: 1;
|
||||
-drawing-line-cap: 1;
|
||||
-drawing-fill-rule: 0;
|
||||
-drawing-dash-array-on: 5px;
|
||||
-drawing-dash-array-off: 15px;
|
||||
-drawing-dash-offset: 0px;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<polygon fill="#555" stroke="transparent" fill-rule="evenodd" points="100,10 40,190 190,74 10,74 160,190"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 219 B |
|
|
@ -0,0 +1,3 @@
|
|||
<svg viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<polygon fill="#555" stroke="transparent" fill-rule="nonzero" points="100,10 40,190 190,74 10,74 160,190"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 219 B |
72
draw.js
72
draw.js
|
|
@ -49,18 +49,22 @@ const _ = imports.gettext.domain(Me.metadata['gettext-domain']).gettext;
|
|||
|
||||
const GS_VERSION = Config.PACKAGE_VERSION;
|
||||
|
||||
const FILL_ICON_PATH = Me.dir.get_child('data').get_child('icons').get_child('fill-symbolic.svg').get_path();
|
||||
const STROKE_ICON_PATH = Me.dir.get_child('data').get_child('icons').get_child('stroke-symbolic.svg').get_path();
|
||||
const LINEJOIN_ICON_PATH = Me.dir.get_child('data').get_child('icons').get_child('linejoin-symbolic.svg').get_path();
|
||||
const LINECAP_ICON_PATH = Me.dir.get_child('data').get_child('icons').get_child('linecap-symbolic.svg').get_path();
|
||||
const DASHED_LINE_ICON_PATH = Me.dir.get_child('data').get_child('icons').get_child('dashed-line-symbolic.svg').get_path();
|
||||
const FULL_LINE_ICON_PATH = Me.dir.get_child('data').get_child('icons').get_child('full-line-symbolic.svg').get_path();
|
||||
const ICON_DIR = Me.dir.get_child('data').get_child('icons');
|
||||
const FILL_ICON_PATH = ICON_DIR.get_child('fill-symbolic.svg').get_path();
|
||||
const STROKE_ICON_PATH = ICON_DIR.get_child('stroke-symbolic.svg').get_path();
|
||||
const LINEJOIN_ICON_PATH = ICON_DIR.get_child('linejoin-symbolic.svg').get_path();
|
||||
const LINECAP_ICON_PATH = ICON_DIR.get_child('linecap-symbolic.svg').get_path();
|
||||
const FILLRULE_NONZERO_ICON_PATH = ICON_DIR.get_child('fillrule-nonzero-symbolic.svg').get_path();
|
||||
const FILLRULE_EVENODD_ICON_PATH = ICON_DIR.get_child('fillrule-evenodd-symbolic.svg').get_path();
|
||||
const DASHED_LINE_ICON_PATH = ICON_DIR.get_child('dashed-line-symbolic.svg').get_path();
|
||||
const FULL_LINE_ICON_PATH = ICON_DIR.get_child('full-line-symbolic.svg').get_path();
|
||||
|
||||
var Shapes = { NONE: 0, LINE: 1, ELLIPSE: 2, RECTANGLE: 3, TEXT: 4, POLYGON: 5, POLYLINE: 6 };
|
||||
const TextState = { DRAWING: 0, WRITING: 1 };
|
||||
const ShapeNames = { 0: "Free drawing", 1: "Line", 2: "Ellipse", 3: "Rectangle", 4: "Text", 5: "Polygon", 6: "Polyline" };
|
||||
const LineCapNames = { 0: 'Butt', 1: 'Round', 2: 'Square' };
|
||||
const LineJoinNames = { 0: 'Miter', 1: 'Round', 2: 'Bevel' };
|
||||
const FillRuleNames = { 0: 'Nonzero', 1: 'Evenodd' };
|
||||
const FontWeightNames = { 0: 'Normal', 1: 'Bold' };
|
||||
const FontStyleNames = { 0: 'Normal', 1: 'Italic', 2: 'Oblique' };
|
||||
const FontFamilyNames = { 0: 'Default', 1: 'Sans-Serif', 2: 'Serif', 3: 'Monospace', 4: 'Cursive', 5: 'Fantasy' };
|
||||
|
|
@ -155,6 +159,7 @@ var DrawingArea = new Lang.Class({
|
|||
this.currentLineWidth = themeNode.get_length('-drawing-line-width');
|
||||
this.currentLineJoin = themeNode.get_double('-drawing-line-join');
|
||||
this.currentLineCap = themeNode.get_double('-drawing-line-cap');
|
||||
this.currentFillRule = themeNode.get_double('-drawing-fill-rule');
|
||||
this.dashArray = [themeNode.get_length('-drawing-dash-array-on'), themeNode.get_length('-drawing-dash-array-off')];
|
||||
this.dashOffset = themeNode.get_length('-drawing-dash-offset');
|
||||
let font = themeNode.get_font();
|
||||
|
|
@ -179,6 +184,7 @@ var DrawingArea = new Lang.Class({
|
|||
this.currentLineWidth = (this.currentLineWidth > 0) ? this.currentLineWidth : 3;
|
||||
this.currentLineJoin = ([0, 1, 2].indexOf(this.currentLineJoin) != -1) ? this.currentLineJoin : Cairo.LineJoin.ROUND;
|
||||
this.currentLineCap = ([0, 1, 2].indexOf(this.currentLineCap) != -1) ? this.currentLineCap : Cairo.LineCap.ROUND;
|
||||
this.currentFillRule = ([0, 1].indexOf(this.currentFillRule) != -1) ? this.currentFillRule : Cairo.FillRule.WINDING;
|
||||
this.currentFontFamilyId = 0;
|
||||
this.currentFontWeight = this.currentFontWeight > 500 ? 1 : 0 ;
|
||||
// font style enum order of Cairo and Pango are different
|
||||
|
|
@ -384,6 +390,7 @@ var DrawingArea = new Lang.Class({
|
|||
line: { lineWidth: this.currentLineWidth, lineJoin: this.currentLineJoin, lineCap: this.currentLineCap },
|
||||
dash: { array: this.dashedLine ? this.dashArray : [0, 0] , offset: this.dashedLine ? this.dashOffset : 0 },
|
||||
fill: this.fill,
|
||||
fillRule: this.currentFillRule,
|
||||
eraser: eraser,
|
||||
transform: { active: false, center: [0, 0], angle: 0, startAngle: 0, ratio: 1 },
|
||||
text: '',
|
||||
|
|
@ -647,6 +654,11 @@ var DrawingArea = new Lang.Class({
|
|||
this.emit('show-osd', null, _(LineCapNames[this.currentLineCap]), "", -1);
|
||||
},
|
||||
|
||||
toggleFillRule: function() {
|
||||
this.currentFillRule = this.currentFillRule == 1 ? 0 : this.currentFillRule + 1;
|
||||
this.emit('show-osd', null, _(FillRuleNames[this.currentFillRule]), "", -1);
|
||||
},
|
||||
|
||||
toggleFontWeight: function() {
|
||||
this.currentFontWeight = this.currentFontWeight == 1 ? 0 : this.currentFontWeight + 1;
|
||||
if (this.currentElement) {
|
||||
|
|
@ -920,6 +932,10 @@ const DrawingElement = new Lang.Class({
|
|||
_init: function(params) {
|
||||
for (let key in params)
|
||||
this[key] = params[key];
|
||||
|
||||
// compatibility with json generated by old extension versions
|
||||
if (params.fillRule === undefined)
|
||||
this.fillRule = Cairo.FillRule.WINDING;
|
||||
},
|
||||
|
||||
// toJSON is called by JSON.stringify
|
||||
|
|
@ -930,6 +946,7 @@ const DrawingElement = new Lang.Class({
|
|||
line: this.line,
|
||||
dash: this.dash,
|
||||
fill: this.fill,
|
||||
fillRule: this.fillRule,
|
||||
eraser: this.eraser,
|
||||
transform: this.transform,
|
||||
text: this.text,
|
||||
|
|
@ -942,6 +959,7 @@ const DrawingElement = new Lang.Class({
|
|||
cr.setLineCap(this.line.lineCap);
|
||||
cr.setLineJoin(this.line.lineJoin);
|
||||
cr.setLineWidth(this.line.lineWidth);
|
||||
cr.setFillRule(this.fillRule);
|
||||
|
||||
if (this.dash.array[0] > 0 && this.dash.array[1] > 0)
|
||||
cr.setDash(this.dash.array, this.dash.offset);
|
||||
|
|
@ -1019,8 +1037,8 @@ const DrawingElement = new Lang.Class({
|
|||
`stroke-linecap="${LineCapNames[this.line.lineCap].toLowerCase()}"`;
|
||||
else
|
||||
attributes = `fill="${fill ? color : 'transparent'}" ` +
|
||||
(fill ? `fill-rule="${FillRuleNames[this.fillRule].toLowerCase()}" ` : `fill-opacity="0" `) +
|
||||
`stroke="${color}" ` +
|
||||
`${fill ? '' : 'fill-opacity="0"'} ` +
|
||||
`stroke-width="${this.line.lineWidth}" ` +
|
||||
`stroke-linecap="${LineCapNames[this.line.lineCap].toLowerCase()}" ` +
|
||||
`stroke-linejoin="${LineJoinNames[this.line.lineJoin].toLowerCase()}"`;
|
||||
|
|
@ -1404,6 +1422,8 @@ const DrawingMenu = new Lang.Class({
|
|||
|
||||
this.strokeIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(STROKE_ICON_PATH) });
|
||||
this.fillIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(FILL_ICON_PATH) });
|
||||
this.fillRuleNonzeroIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(FILLRULE_NONZERO_ICON_PATH) });
|
||||
this.fillRuleEvenoddIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(FILLRULE_EVENODD_ICON_PATH) });
|
||||
this.linejoinIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(LINEJOIN_ICON_PATH) });
|
||||
this.linecapIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(LINECAP_ICON_PATH) });
|
||||
this.fullLineIcon = new Gio.FileIcon({ file: Gio.File.new_for_path(FULL_LINE_ICON_PATH) });
|
||||
|
|
@ -1463,9 +1483,12 @@ const DrawingMenu = new Lang.Class({
|
|||
this.menu.addAction(_("Smooth"), this.area.smoothLastElement.bind(this.area), 'format-text-strikethrough-symbolic');
|
||||
this._addSeparator(this.menu);
|
||||
|
||||
this._addSubMenuItem(this.menu, null, ShapeNames, this.area, 'currentShape', this.updateSectionVisibility.bind(this));
|
||||
this._addSubMenuItem(this.menu, null, ShapeNames, this.area, 'currentShape', this._updateSectionVisibility.bind(this));
|
||||
this._addColorSubMenuItem(this.menu);
|
||||
this.fillItem = this._addSwitchItem(this.menu, _("Fill"), this.strokeIcon, this.fillIcon, this.area, 'fill');
|
||||
this.fillItem = this._addSwitchItem(this.menu, _("Fill"), this.strokeIcon, this.fillIcon, this.area, 'fill', this._updateSectionVisibility.bind(this));
|
||||
this.fillSection = new PopupMenu.PopupMenuSection();
|
||||
this._addSubMenuItem(this.fillSection, this.fillRuleNonzeroIcon, FillRuleNames, this.area, 'currentFillRule', this._updateFillRuleIcon.bind(this));
|
||||
this.menu.addMenuItem(this.fillSection);
|
||||
this._addSeparator(this.menu);
|
||||
|
||||
let lineSection = new PopupMenu.PopupMenuSection();
|
||||
|
|
@ -1489,10 +1512,10 @@ const DrawingMenu = new Lang.Class({
|
|||
this.fontSection = fontSection;
|
||||
|
||||
let manager = Extension.manager;
|
||||
this._addSwitchItemWithCallback(this.menu, _("Hide panel and dock"), manager.hiddenList ? true : false, manager.togglePanelAndDockOpacity.bind(manager));
|
||||
this._addSwitchItemWithCallback(this.menu, _("Add a drawing background"), this.area.hasBackground, this.area.toggleBackground.bind(this.area));
|
||||
this._addSwitchItemWithCallback(this.menu, _("Add a grid overlay"), this.area.hasGrid, this.area.toggleGrid.bind(this.area));
|
||||
this._addSwitchItemWithCallback(this.menu, _("Square drawing area"), this.area.isSquareArea, this.area.toggleSquareArea.bind(this.area));
|
||||
this._addSimpleSwitchItem(this.menu, _("Hide panel and dock"), manager.hiddenList ? true : false, manager.togglePanelAndDockOpacity.bind(manager));
|
||||
this._addSimpleSwitchItem(this.menu, _("Add a drawing background"), this.area.hasBackground, this.area.toggleBackground.bind(this.area));
|
||||
this._addSimpleSwitchItem(this.menu, _("Add a grid overlay"), this.area.hasGrid, this.area.toggleGrid.bind(this.area));
|
||||
this._addSimpleSwitchItem(this.menu, _("Square drawing area"), this.area.isSquareArea, this.area.toggleSquareArea.bind(this.area));
|
||||
this._addSeparator(this.menu);
|
||||
|
||||
this._addDrawingNameItem(this.menu);
|
||||
|
|
@ -1503,22 +1526,35 @@ const DrawingMenu = new Lang.Class({
|
|||
this.menu.addAction(_("Edit style"), manager.openUserStyleFile.bind(manager), 'document-page-setup-symbolic');
|
||||
this.menu.addAction(_("Show help"), () => { this.close(); this.area.toggleHelp(); }, 'preferences-desktop-keyboard-shortcuts-symbolic');
|
||||
|
||||
this.updateSectionVisibility();
|
||||
this._updateSectionVisibility();
|
||||
this._updateFillRuleIcon();
|
||||
},
|
||||
|
||||
updateSectionVisibility: function() {
|
||||
_updateSectionVisibility: function() {
|
||||
if (this.area.currentShape != Shapes.TEXT) {
|
||||
this.lineSection.actor.show();
|
||||
this.fontSection.actor.hide();
|
||||
this.fillItem.setSensitive(true);
|
||||
this.fillSection.setSensitive(true);
|
||||
} else {
|
||||
this.lineSection.actor.hide();
|
||||
this.fontSection.actor.show();
|
||||
this.fillItem.setSensitive(false);
|
||||
this.fillSection.setSensitive(false);
|
||||
}
|
||||
|
||||
if (this.area.fill)
|
||||
this.fillSection.actor.show();
|
||||
else
|
||||
this.fillSection.actor.hide();
|
||||
},
|
||||
|
||||
_addSwitchItem: function(menu, label, iconFalse, iconTrue, target, targetProperty) {
|
||||
_updateFillRuleIcon: function() {
|
||||
let fillRuleIcon = this.area.currentFillRule == Cairo.FillRule.EVEN_ODD ? this.fillRuleEvenoddIcon : this.fillRuleNonzeroIcon;
|
||||
this.fillSection.firstMenuItem.icon.set_gicon(fillRuleIcon);
|
||||
},
|
||||
|
||||
_addSwitchItem: function(menu, label, iconFalse, iconTrue, target, targetProperty, onToggled) {
|
||||
let item = new PopupMenu.PopupSwitchMenuItem(label, target[targetProperty]);
|
||||
|
||||
item.icon = new St.Icon({ style_class: 'popup-menu-icon' });
|
||||
|
|
@ -1528,12 +1564,14 @@ const DrawingMenu = new Lang.Class({
|
|||
item.connect('toggled', (item, state) => {
|
||||
target[targetProperty] = state;
|
||||
item.icon.set_gicon(target[targetProperty] ? iconTrue : iconFalse);
|
||||
if (onToggled)
|
||||
onToggled();
|
||||
});
|
||||
menu.addMenuItem(item);
|
||||
return item;
|
||||
},
|
||||
|
||||
_addSwitchItemWithCallback: function(menu, label, active, onToggled) {
|
||||
_addSimpleSwitchItem: function(menu, label, active, onToggled) {
|
||||
let item = new PopupMenu.PopupSwitchMenuItem(label, active);
|
||||
item.connect('toggled', onToggled);
|
||||
menu.addMenuItem(item);
|
||||
|
|
|
|||
|
|
@ -184,6 +184,7 @@ var AreaManager = new Lang.Class({
|
|||
'decrement-line-width-more': () => this.activeArea.incrementLineWidth(-5),
|
||||
'toggle-linejoin': this.activeArea.toggleLineJoin.bind(this.activeArea),
|
||||
'toggle-linecap': this.activeArea.toggleLineCap.bind(this.activeArea),
|
||||
'toggle-fill-rule': this.activeArea.toggleFillRule.bind(this.activeArea),
|
||||
'toggle-dash' : this.activeArea.toggleDash.bind(this.activeArea),
|
||||
'toggle-fill' : this.activeArea.toggleFill.bind(this.activeArea),
|
||||
'select-none-shape': () => this.activeArea.selectShape(Draw.Shapes.NONE),
|
||||
|
|
|
|||
|
|
@ -200,6 +200,9 @@ msgstr ""
|
|||
msgid "Change linecap"
|
||||
msgstr ""
|
||||
|
||||
msgid "Change fill rule"
|
||||
msgstr ""
|
||||
|
||||
#: already in draw.js
|
||||
#:msgid "Dashed line"
|
||||
#:msgstr ""
|
||||
|
|
@ -372,6 +375,12 @@ msgstr ""
|
|||
#msgid "Bevel"
|
||||
#msgstr ""
|
||||
|
||||
#msgid "Nonzero"
|
||||
#msgstr ""
|
||||
|
||||
#msgid "Evenodd"
|
||||
#msgstr ""
|
||||
|
||||
#msgid "Normal"
|
||||
#msgstr ""
|
||||
|
||||
|
|
|
|||
1
prefs.js
1
prefs.js
|
|
@ -60,6 +60,7 @@ var INTERNAL_KEYBINDINGS = {
|
|||
'decrement-line-width-more': "Decrement line width even more",
|
||||
'toggle-linejoin': "Change linejoin",
|
||||
'toggle-linecap': "Change linecap",
|
||||
'toggle-fill-rule': "Change fill rule",
|
||||
'toggle-dash': "Dashed line",
|
||||
'-separator-3': '',
|
||||
'toggle-font-family': "Change font family (generic name)",
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -107,12 +107,12 @@
|
|||
<description>unselect shape (free drawing)</description>
|
||||
</key>
|
||||
<key type="as" name="increment-line-width">
|
||||
<default>["<Primary>KP_Add"]</default>
|
||||
<default><![CDATA[['<Primary>KP_Add','<Primary><Shift>plus']]]></default>
|
||||
<summary>increment the line width</summary>
|
||||
<description>increment the line width</description>
|
||||
</key>
|
||||
<key type="as" name="decrement-line-width">
|
||||
<default>["<Primary>KP_Subtract"]</default>
|
||||
<default><![CDATA[['<Primary>KP_Subtract','<Primary>minus','<Primary><Shift>minus']]]></default>
|
||||
<summary>decrement the line width</summary>
|
||||
<description>decrement the line width</description>
|
||||
</key>
|
||||
|
|
@ -136,6 +136,11 @@
|
|||
<summary>toggle linecap</summary>
|
||||
<description>toggle linecap</description>
|
||||
</key>
|
||||
<key type="as" name="toggle-fill-rule">
|
||||
<default><![CDATA[['<Primary>KP_Multiply','<Primary>asterisk','<Primary><Shift>asterisk']]]></default>
|
||||
<summary>toggle fill rule</summary>
|
||||
<description>toggle fill rule</description>
|
||||
</key>
|
||||
<key type="as" name="toggle-dash">
|
||||
<default>["<Primary>period"]</default>
|
||||
<summary>toggle dash</summary>
|
||||
|
|
|
|||
Loading…
Reference in New Issue