增加ttf管理器

This commit is contained in:
mkwiser
2014-10-07 02:34:38 +08:00
parent 917d134698
commit 168984c777
18 changed files with 939 additions and 96 deletions

44
css/bootstrap.less vendored Normal file
View File

@@ -0,0 +1,44 @@
// overwrite bootstrap themes
.modal-dialog {
margin-top: 100px;
}
.modal-header {
padding-top: 6px;
padding-bottom: 6px;
background: #327EC0;
color: #FFF;
.close {
margin-top: 3px;
}
.modal-title {
font-size: 14px;
line-height: 25px;
}
}
.modal-footer {
padding-top: 10px;
padding-bottom: 10px;
}
.modal-body {
min-height: 100px;
}
.modal-content {
border-color: rgba(0,0,0,.5);
-webkit-box-shadow: 0 2px 4px rgba(0,0,0,.2);
box-shadow: 0 2px 4px rgba(0,0,0,.2);
overflow: hidden;
}
.dropdown-menu {
a {
cursor: pointer;
}
}

View File

@@ -1,3 +1,35 @@
.modal-dialog {
margin-top: 100px;
}
.modal-header {
padding-top: 6px;
padding-bottom: 6px;
background: #327EC0;
color: #FFF;
}
.modal-header .close {
margin-top: 3px;
}
.modal-header .modal-title {
font-size: 14px;
line-height: 25px;
}
.modal-footer {
padding-top: 10px;
padding-bottom: 10px;
}
.modal-body {
min-height: 100px;
}
.modal-content {
border-color: rgba(0, 0, 0, 0.5);
-webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
overflow: hidden;
}
.dropdown-menu a {
cursor: pointer;
}
body,
html {
margin: 0;
@@ -28,6 +60,7 @@ html {
border-radius: 0;
margin: 0;
position: fixed;
z-index: 10;
width: 100%;
top: 0;
}
@@ -35,7 +68,7 @@ html {
margin-right: 10px;
margin-top: 10px;
}
.navbar .btn:first-child {
.navbar > .btn:first-child {
margin-left: 10px;
}
#export-btn {
@@ -74,3 +107,11 @@ html {
text-align: center;
display: none;
}
.selection-range {
position: absolute;
z-index: 6;
display: none;
border: 1px solid #CCC;
background: rgba(222, 222, 222, 0.5);
pointer-events: none;
}

View File

@@ -1,4 +1,6 @@
@import './bootstrap.less';
body, html {
margin: 0;
padding: 0;
@@ -35,6 +37,7 @@ body, html {
border-radius: 0;
margin: 0;
position: fixed;
z-index: 10;
width: 100%;
top: 0;
@@ -43,7 +46,7 @@ body, html {
margin-top: 10px;
}
.btn:first-child {
>.btn:first-child {
margin-left: 10px;
}
}
@@ -89,3 +92,13 @@ body, html {
text-align: center;
display: none;
}
.selection-range {
position: absolute;
z-index: 6;
display: none;
border: 1px solid #CCC;
background: rgba(222, 222, 222, 0.5);
pointer-events: none;
}

View File

@@ -2,3 +2,23 @@
font-family: 'fonteditor';
src: url('../font/iconfont.ttf') format('truetype');
}
.i-edit,
.i-del {
display: inline-block;
font-family: 'fonteditor';
font-size: 12px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0.1px;
}
.i-edit:hover,
.i-del:hover {
cursor: pointer;
color: blue;
}
.i-edit:before {
content: '\e605';
}
.i-del:before {
content: '\e611';
}

View File

@@ -6,3 +6,25 @@
src: url('../font/iconfont.ttf') format('truetype');
}
.i-edit,
.i-del {
display: inline-block;
font-family: 'fonteditor';
font-size: 12px;
font-style:normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0.1px;
&:hover {
cursor: pointer;
color: blue;
}
}
.i-edit:before {
content: '\e605';
}
.i-del:before {
content: '\e611';
}

View File

@@ -1,3 +1,35 @@
.modal-dialog {
margin-top: 100px;
}
.modal-header {
padding-top: 6px;
padding-bottom: 6px;
background: #327EC0;
color: #FFF;
}
.modal-header .close {
margin-top: 3px;
}
.modal-header .modal-title {
font-size: 14px;
line-height: 25px;
}
.modal-footer {
padding-top: 10px;
padding-bottom: 10px;
}
.modal-body {
min-height: 100px;
}
.modal-content {
border-color: rgba(0, 0, 0, 0.5);
-webkit-box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
overflow: hidden;
}
.dropdown-menu a {
cursor: pointer;
}
body,
html {
margin: 0;
@@ -28,6 +60,7 @@ html {
border-radius: 0;
margin: 0;
position: fixed;
z-index: 10;
width: 100%;
top: 0;
}
@@ -35,7 +68,7 @@ html {
margin-right: 10px;
margin-top: 10px;
}
.navbar .btn:first-child {
.navbar > .btn:first-child {
margin-left: 10px;
}
#export-btn {
@@ -74,26 +107,64 @@ html {
text-align: center;
display: none;
}
.selection-range {
position: absolute;
z-index: 6;
display: none;
border: 1px solid #CCC;
background: rgba(222, 222, 222, 0.5);
pointer-events: none;
}
@font-face {
font-family: 'fonteditor';
src: url('../font/iconfont.ttf') format('truetype');
}
.i-edit,
.i-del {
display: inline-block;
font-family: 'fonteditor';
font-size: 12px;
font-style: normal;
-webkit-font-smoothing: antialiased;
-webkit-text-stroke-width: 0.1px;
}
.i-edit:hover,
.i-del:hover {
cursor: pointer;
color: blue;
}
.i-edit:before {
content: '\e605';
}
.i-del:before {
content: '\e611';
}
.project .project-title {
font-weight: bold;
}
.project .project-list {
line-height: 20px;
line-height: 24px;
}
.project .project-list div {
padding-left: 10px;
padding: 0 10px;
}
.project .project-list div:hover {
color: red;
text-decoration: underline;
cursor: pointer;
background: #EFEFEF;
}
.project .project-list div:hover .i-del {
display: block;
}
.project .project-list .i-del {
float: right;
display: none;
}
.glyf-list {
padding-bottom: 40px;
overflow: hidden;
}
.glyf-list > .glyf-item {
float: left;
position: relative;
margin: 10px;
width: 86px;
border: 1px solid #CCC;
@@ -123,12 +194,34 @@ html {
.glyf-list > .glyf-item .glyf .path {
fill: green;
}
.glyf-list > .glyf-item .i-del,
.glyf-list > .glyf-item .i-edit {
position: absolute;
right: 2px;
display: none;
}
.glyf-list > .glyf-item .i-edit {
right: 20px;
}
.glyf-list > .glyf-item:hover {
background: #EFEFEF;
}
.glyf-list > .glyf-item:hover .path {
fill: darkgreen;
}
.glyf-list > .glyf-item:hover .i-del,
.glyf-list > .glyf-item:hover .i-edit {
display: block;
}
.glyf-list > .compound .path {
fill: lightgreen!important;
}
.glyf-list > .new .path {
fill: blue!important;
}
.glyf-list > .selected {
background: #EBFFC2!important;
}
.glyf-list.no-hover .glyf-item {
pointer-events: none;
}

View File

@@ -10,15 +10,23 @@
font-weight: bold;
}
.project-list {
line-height: 20px;
line-height: 24px;
div {
padding-left: 10px;
padding: 0 10px;
}
div:hover {
color: red;
text-decoration: underline;
cursor: pointer;
background: #EFEFEF;
.i-del {
display: block;
}
}
.i-del {
float: right;
display: none;
}
}
}
@@ -27,9 +35,13 @@
.glyf-list {
padding-bottom: 40px;
overflow: hidden;
>.glyf-item {
float: left;
position: relative;
margin: 10px;
width: 86px;
border: 1px solid #CCC;
@@ -59,6 +71,17 @@
fill: green;
}
}
.i-del,
.i-edit {
position: absolute;
right: 2px;
display: none;
}
.i-edit {
right: 20px;
}
}
>.glyf-item:hover {
@@ -66,6 +89,17 @@
.path {
fill: darkgreen;
}
.i-del,
.i-edit {
display: block;
}
}
>.compound {
.path {
fill: lightgreen!important;
}
}
>.new {
@@ -73,4 +107,15 @@
fill: blue!important;
}
}
>.selected {
background: #EBFFC2!important;
}
}
.glyf-list.no-hover {
.glyf-item {
pointer-events: none;
}
}

Binary file not shown.

View File

@@ -0,0 +1,45 @@
/**
* @file setting-unicode.js
* @author mengke01
* @date
* @description
* 设置代码点
*/
define(
function(require) {
var tpl = ''
+ '<div class="col-lg-6">'
+ '<div class="input-group">'
+ '<div class="input-group-btn">'
+ '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">起始代码点 <span class="caret"></span></button>'
+ '<ul class="dropdown-menu" role="menu">'
+ '<li><a href="javascript:$(\'#setting-text-unicode\').val(\'$20\')">ascii</a></li>'
+ '<li><a href="javascript:$(\'#setting-text-unicode\').val(\'$E001\')">unicode private data</a></li>'
+ '</ul>'
+ '</div>'
+ '<input id="setting-text-unicode" type="text" class="form-control" value="$E001">'
+ '</div>'
+ '</div>';
return require('./setting').derive({
getTpl: function() {
return tpl;
},
onConfirm: function() {
var unicode = $('#setting-text-unicode').val();
if (unicode.match(/^\$[A-E0-9]+$/i)) {
this.fire('change', {
unicode: unicode
});
}
else {
alert('代码点设置不正确');
return false;
}
}
});
}
);

View File

@@ -0,0 +1,104 @@
/**
* @file setting.js
* @author mengke01
* @date
* @description
* 设置框
*/
define(
function(require) {
var lang = require('common/lang');
var observable = require('common/observable');
/**
* 设置框函数
*
* @constructor
*/
function Setting() {
}
/**
* 初始化绑定事件
*/
Setting.prototype.preInit = function() {
var dlg = $('#model-dialog');
dlg.find('.modal-title').html(this.title);
dlg.find('.modal-body').html(this.getTpl());
dlg.on('hidden.bs.modal', lang.bind(function (e) {
if (dlg) {
this.un();
dlg.off('hidden.bs.modal');
dlg.find('.btn-confirm').off('click');
dlg = null;
}
}, this));
dlg.find('.btn-confirm').on('click', lang.bind(function() {
if (false !== this.onConfirm()) {
dlg.modal('hide');
}
}, this));
};
/**
* 获取模板
*
* @return {string} 模板字符串
*/
Setting.prototype.getTpl = function() {
return '';
};
/**
* 确定事件
*
* @return {boolean=} 是否关闭对话框
*/
Setting.prototype.onConfirm = function() {
};
/**
* 显示
*/
Setting.prototype.show = function() {
$('#model-dialog').modal('show');
return this;
};
/**
* 注销
*/
Setting.prototype.dispose = function() {
$('#model-dialog').modal('hide');
};
/**
* 派生一个setting
*
* @param {Object} proto 原型函数
* @return {Function} 派生类
*/
Setting.derive = function(proto) {
function Class() {
Setting.apply(this, arguments);
this.preInit();
this.initialize && this.initialize();
}
Class.prototype = new Setting();
Class.prototype.constructor = Setting;
lang.extend(Class.prototype, proto);
observable.mixin(Class.prototype);
return Class;
};
return Setting;
}
);

View File

@@ -14,37 +14,72 @@ define(
var exporter = require('../widget/exporter');
var project = require('../widget/project');
var ProjectViewer = require('../widget/projectviewer');
var ttfmanager = require('../widget/ttfmanager');
var TTFManager = require('../widget/ttfmanager');
var program = require('../program');
var string = require('common/string');
var setting = {
'unicode': require('../dialog/setting-unicode')
}
var actions = {
new: function() {
if (program.data.ttf && !window.confirm('是否放弃保存当前项目?')) {
'new': function() {
if (program.ttfmanager.get() && !window.confirm('是否放弃保存当前项目?')) {
return;
}
newEmpty();
},
open: function() {
'open': function() {
$('#font-import').click();
},
import: function() {
'import': function() {
$('#font-import').click();
},
export: function() {
'export': function() {
},
save: function() {
'save': function() {
saveProj();
},
'add-new': function() {
program.ttfmanager.addglyf({
name: '',
unicode:[]
});
},
'setting-unicode': function(e) {
var dlg = new setting.unicode();
dlg.on('change', function(e) {
// 此处延迟处理
setTimeout(function(){
setUnicode(e.unicode);
}, 20);
});
dlg.show();
}
};
// 设置unicode
function setUnicode(unicode) {
if (program.ttfmanager.get()) {
var glyfList = program.viewer.getSelected();
program.ttfmanager.setUnicode(unicode, glyfList);
}
}
// 保存项目
function saveProj() {
if (program.data.ttf) {
if (program.ttfmanager.get()) {
var name = '';
if(name = window.prompt('请输入项目名称:')) {
var list = project.add(string.encodeHTML(name), program.data.ttf);
var list = project.add(string.encodeHTML(name), program.ttfmanager.get());
program.projectViewer.show(list);
}
}
@@ -53,8 +88,7 @@ define(
// 新建空白
function newEmpty() {
$.getJSON('./src/fonteditor/data/empty.json', function(imported) {
program.data.ttf = imported;
program.viewer.show(imported);
program.ttfmanager.set(imported);
})
}
@@ -63,23 +97,20 @@ define(
var file = e.target.files[0];
if (program.action == 'open' && file.name.match(/(\.ttf|\.woff)$/)) {
program.data.file = file.name;
loader.load(file, {
type: file.name.slice(file.name.lastIndexOf('.') + 1),
success: function(imported) {
program.data.ttf = imported;
program.viewer.show(imported);
program.ttfmanager.set(imported);
}
});
}
else if (program.action == 'import' && file.name.match(/(\.ttf|\.woff|\.svg)$/)) {
if (program.data.ttf) {
if (program.ttfmanager.get()) {
loader.load(file, {
type: file.name.slice(file.name.lastIndexOf('.') + 1),
success: function(imported) {
if (imported.glyf.length) {
ttfmanager.combine(program.data.ttf, imported, {scale: true});
program.viewer.show(program.data.ttf);
program.ttfmanager.combine(imported, {scale: true});
}
}
});
@@ -93,10 +124,9 @@ define(
}
function exportFile(e) {
var ttf = program.data.ttf;
if (ttf) {
if (program.ttfmanager.get()) {
var target = $(e.target);
exporter.export(ttf, {
exporter.export(program.ttfmanager.get(), {
type: target.attr('data-type'),
target: target
});
@@ -128,21 +158,39 @@ define(
init: function () {
bindEvent();
// 查看器
program.viewer = new GLYFViewer($('#glyf-list'));
program.viewer.on('del', function(e) {
if (e.list) {
program.ttfmanager.delglyf(e.list);
}
});
// 项目管理
program.projectViewer = new ProjectViewer($('#project-list'));
program.projectViewer.on('open', function(e) {
var imported = project.get(e.projectName);
if (imported) {
if (program.data.ttf && !window.confirm('是否放弃保存当前项目?')) {
if (program.ttfmanager.get() && !window.confirm('是否放弃保存当前项目?')) {
return;
}
program.data.ttf = imported;
program.viewer.show(imported);
program.ttfmanager.set(imported);
}
});
program.projectViewer.on('del', function(e) {
if (e.projectName && window.confirm('是否删除项目?')) {
program.projectViewer.show(project.remove(e.projectName));
}
});
program.projectViewer.show(project.items());
// ttf管理
program.ttfmanager = new TTFManager();
program.ttfmanager.on('change', function(e) {
program.viewer.show(e.ttf);
});
}
};

View File

@@ -10,11 +10,15 @@ define(
function(require) {
var glyf2svg = require('ttf/util/glyf2svg');
var string = require('common/string');
var lang = require('common/lang');
var MouseCapture = require('render/capture/Mouse');
var isBoundingBoxCross = require('graphics/isBoundingBoxCross');
var GLYF_ITEM_TPL = ''
+ '<div data-index="${index}" class="glyf-item ${compound} ${modify}">'
+ '<i data-action="edit" class="i-edit" title="编辑"></i><i data-action="del" class="i-del" title="删除"></i>'
+ '<svg class="glyf" viewbox="0 0 ${unitsPerEm} ${unitsPerEm}"><g transform="scale(1, -1) translate(0, -${descent}) scale(0.95, 0.95) "><path class="path" ${d}/></g></svg>'
+ '<div class="unicode" title="${unicode}">${unicode}</div><div class="name" title="${name}">${name}</div>'
+ '<div data-field="unicode" class="unicode" title="${unicode}">${unicode}</div><div data-field="name" class="name" title="${name}">${name}</div>'
+ '</div>';
@@ -46,6 +50,28 @@ define(
this.main.html(glyfStr);
}
// 点击item
function clickItem(e) {
$(this).toggleClass('selected');
}
// 点击item
function clickAction(e) {
e.stopPropagation();
var target = $(e.target);
var action = target.attr('data-action');
if (action == 'del' && !window.confirm('确定删除字形么?')) {
return;
}
var selected = [+target.parent().attr('data-index')];
this.fire(action, {
list: selected
});
}
/**
* glyf查看器
*
@@ -56,12 +82,129 @@ define(
function GlyfViewer(main, options) {
this.options = options || {};
this.main = $(main);
this.main.delegate('[data-index]', 'click', clickItem)
.delegate('[data-action]', 'click', lang.bind(clickAction, this));
var me = this;
// 绑定键盘事件
me.listener = function(e) {
// 删除
if (46 === e.keyCode) {
e.stopPropagation();
var selected = me.getSelected();
if (selected.length) {
me.fire('del', {
list: selected
});
}
}
// 取消选中
else if (27 === e.keyCode) {
me.main.children().removeClass('selected');
}
};
$(document.body).on('click', function(e) {
var focused = me.main.get(0) === e.target || me.main.get(0).contains(e.target);
if (focused && !me.listening) {
document.body.addEventListener('keyup', me.listener,false);
me.listening = true;
}
else if (!focused){
document.body.removeEventListener('keyup', me.listener);
me.listening = false;
}
});
// 选择范围内元素
function selectRangeItem(bound, toggle, remove) {
me.main.children().each(function(i, element) {
var item = $(element);
var pos = item.offset();
var b = {
x: pos.left,
y: pos.top,
width: item.width(),
height: item.height()
}
if (3 === isBoundingBoxCross(bound, b)) {
if (toggle) {
item.toggleClass('selected');
}
else if (remove) {
item.removeClass('selected')
}
else {
item.addClass('selected')
}
}
});
}
me.capture = new MouseCapture(me.main.get(0), {
events: {
dblclick: false,
mousewheel: false,
mouseover: false,
mouseout: false
}
});
me.capture.on('dragstart', function(e) {
$('#selection-range').show();
me.main.addClass('no-hover');
me.startX = e.originEvent.pageX;
me.startY = e.originEvent.pageY;
});
var dragging = function(e) {
var x = e.originEvent.pageX;
var y = e.originEvent.pageY;
$('#selection-range').css({
left: Math.min(me.startX, x),
top: Math.min(me.startY, y),
width: Math.abs(me.startX - x),
height: Math.abs(me.startY - y)
});
};
me.capture.on('drag', dragging);
me.capture.on('dragend', function(e) {
$('#selection-range').hide();
me.main.removeClass('no-hover');
var x = e.originEvent.pageX;
var y = e.originEvent.pageY;
var pos = me.main.offset();
selectRangeItem.call(me, {
x: Math.min(me.startX, x),
y: Math.min(me.startY, y),
width: Math.abs(me.startX - x),
height: Math.abs(me.startY - y)
}, e.ctrlKey, e.shiftKey);
});
}
GlyfViewer.prototype.show = function(ttf) {
showGLYF.call(this, ttf);
};
GlyfViewer.prototype.getSelected = function() {
var selected = [];
this.main.find('.selected').each(function(index, item) {
selected.push(+item.getAttribute('data-index'));
});
return selected;
};
require('common/observable').mixin(GlyfViewer.prototype);
return GlyfViewer;

View File

@@ -33,11 +33,22 @@ define(
*/
add: function(projectName, ttf) {
var list = this.items();
var id = Date.now();
list.push({
name: projectName,
id: id
var exist = list.filter(function(l) {
return l.name == projectName;
});
var id;
if (exist.length) {
id = exist[0].id;
}
else {
id = Date.now();
list.push({
name: projectName,
id: id
});
}
storage.setItem('project-list', JSON.stringify(list));
storage.setItem(id, JSON.stringify(ttf));
return list;
@@ -58,6 +69,8 @@ define(
}
}
storage.setItem('project-list', JSON.stringify(list));
return list;
},
/**

View File

@@ -22,7 +22,18 @@ define(
this.main = $(main);
var me = this;
this.main.delegate('[data-name]', 'click', function(e) {
me.main.delegate('[data-action]', 'click', function(e) {
e.stopPropagation();
var the = $(this);
me.fire(the.attr('data-action'), {
projectName: the.parent().attr('data-name')
});
});
me.main.delegate('[data-name]', 'click', function(e) {
e.preventDefault();
e.stopPropagation();
me.fire('open', {
projectName: $(this).attr('data-name')
});
@@ -32,7 +43,7 @@ define(
ProjectViewer.prototype.show = function(projects) {
var str = '';
(projects || []).forEach(function(proj) {
str += '<div data-name="'+ proj.name +'" data-id="'+ proj.id +'"><a href="javascript:;">'+ proj.name +'</a></div>';
str += '<div data-name="'+ proj.name +'" data-id="'+ proj.id +'"><i title="删除" data-action="del" class="i-del"></i><a href="#">'+ proj.name +'</a></div>';
});
this.main.html(str);

View File

@@ -10,49 +10,193 @@
define(
function(require) {
var postName = require('ttf/enum/postName');
var pathAdjust = require('graphics/pathAdjust');
var manager = {
/**
* 合并两个ttfObject此处仅合并简单字形
*
* @param {Object} ttf ttfObject
* @param {Object} imported ttfObject
* @param {Object} options 参数选项
* @param {boolean} options.scale 是否自动缩放
*
* @return {Object} 合并后的ttfObject
*/
combine: function(ttf, imported, options) {
options = options || {};
// 调整glyf以适应打开的文件
var scale = 1;
// 对导入的轮廓进行缩放处理
if (options.scale && imported.head.unitsPerEm && imported.head.unitsPerEm != ttf.head.unitsPerEm) {
scale = ttf.head.unitsPerEm / imported.head.unitsPerEm;
}
/**
* 合并两个ttfObject此处仅合并简单字形
*
* @param {Object} ttf ttfObject
* @param {Object} imported ttfObject
* @param {Object} options 参数选项
* @param {boolean} options.scale 是否自动缩放
*
* @return {Object} 合并后的ttfObject
*/
function combine(ttf, imported, options) {
options = options || {};
imported.glyf.filter(function(g, index) {
return g.contours && g.contours.length //简单轮廓
&& g.name != '.notdef' && g.name != '.null' && g.name != 'nonmarkingreturn'; // 非预定义字形
}).forEach(function(g) {
if (scale !== 1) {
g.contours.forEach(function(contour) {
pathAdjust(contour, scale, scale);
});
}
g.modify = 'new';
ttf.glyf.push(g);
});
return ttf;
// 调整glyf以适应打开的文件
var scale = 1;
// 对导入的轮廓进行缩放处理
if (options.scale && imported.head.unitsPerEm && imported.head.unitsPerEm != ttf.head.unitsPerEm) {
scale = ttf.head.unitsPerEm / imported.head.unitsPerEm;
}
imported.glyf.filter(function(g, index) {
return g.contours && g.contours.length //简单轮廓
&& g.name != '.notdef' && g.name != '.null' && g.name != 'nonmarkingreturn'; // 非预定义字形
}).forEach(function(g) {
if (scale !== 1) {
g.contours.forEach(function(contour) {
pathAdjust(contour, scale, scale);
});
}
g.modify = 'new';
ttf.glyf.push(g);
});
return ttf;
}
/**
* 构造函数
*
* @constructor
* @param {ttfObject} ttf ttf对象
*/
function Manager(ttf) {
this.ttf = ttf;
}
/**
* 设置ttf
*
* @param {ttfObject} ttf ttf对象
* @return {this}
*/
Manager.prototype.set = function(ttf) {
if (this.ttf !== ttf) {
this.ttf = ttf;
this.fire('change', {
ttf: this.ttf
});
}
return this;
};
return manager;
/**
* 获取ttf对象
*
* @return {ttfObject} ttf ttf对象
*/
Manager.prototype.get = function() {
return this.ttf;
};
/**
* 添加glyf
*
* @param {Object} glyf glyf对象
*
* @return {this}
*/
Manager.prototype.addglyf = function(glyf) {
this.ttf.glyf.push(glyf);
this.fire('change', {
ttf: this.ttf
});
return this;
};
/**
* 合并两个ttfObject此处仅合并简单字形
*
* @param {Object} imported ttfObject
* @param {Object} options 参数选项
* @param {boolean} options.scale 是否自动缩放
*
* @return {this}
*/
Manager.prototype.combine = function(imported, options) {
combine(this.ttf, imported, options);
this.fire('change', {
ttf: this.ttf
});
return this;
};
/**
* 删除指定字形
*
* @param {Array} indexList 索引列表
* @return {this}
*/
Manager.prototype.delglyf = function(indexList) {
var glyf = this.ttf.glyf, count = 0;
for(var i = glyf.length - 1; i >= 0; i--) {
if (indexList.indexOf(i) >= 0) {
glyf.splice(i, 1);
count++;
}
}
if (count) {
this.fire('change', {
ttf: this.ttf
});
}
return this;
};
/**
* 设置unicode代码
*
* @param {string} unicode unicode代码
* @param {Array} indexList 索引列表
* @return {this}
*/
Manager.prototype.setUnicode = function(unicode, indexList) {
var glyf = this.ttf.glyf, list;
if (indexList && indexList.length) {
list = indexList.map(function(item) {
return glyf[item];
});
}
else {
list = glyf;
}
list = list.filter(function(g) {
return g.name != '.notdef' && g.name != '.null' && g.name != 'nonmarkingreturn';
});
if (list.length) {
unicode = Number('0x' + unicode.slice(1));
list.forEach(function(g) {
g.unicode = [unicode];
g.name = unicode - 29 < 258 ? postName[unicode - 29] : 'uni' + unicode.toString(16).toUpperCase();
unicode++;
});
this.fire('change', {
ttf: this.ttf
});
}
return this;
};
/**
* 注销
*/
Manager.prototype.dispose = function() {
this.un();
delete this.ttf;
};
require('common/observable').mixin(Manager.prototype);
return Manager;
}
);

View File

@@ -21,7 +21,7 @@ define(
* @return {number} 包含关系
*
* 2 : b2 包含 b1
* 3 : b2 包含 b3
* 3 : b1 包含 b2
* 1 : 有交点
*/
function isBoundingBoxCross(b1, b2) {

View File

@@ -48,7 +48,8 @@ define(
ctrlKey: e.ctrlKey,
metaKey: e.metaKey,
altKey: e.altKey,
shiftKey: e.shiftKey
shiftKey: e.shiftKey,
originEvent: e
};
}
@@ -73,12 +74,13 @@ define(
*/
function mousedown(e) {
prevent(e);
if(false === this.events.mousedown) {
return;
}
prevent(e);
var event = getEvent(e);
this.startX = event.x;
@@ -117,12 +119,13 @@ define(
* @param {Object} e 事件参数
*/
function mousemove(e) {
prevent(e);
if(false === this.events.mousemove) {
return;
}
prevent(e);
var event = getEvent(e);
this.fire('move', event);
@@ -155,12 +158,13 @@ define(
*/
function mouseup(e) {
prevent(e);
if(false === this.events.mouseup) {
return;
}
prevent(e);
var event = getEvent(e);
event.time = Date.now() - this.startTime;
@@ -193,12 +197,12 @@ define(
*/
function mousewheel(e) {
prevent(e);
if(false === this.events.mousewheel) {
return;
}
prevent(e);
var delta = 0;
if (e.wheelDelta) {
delta = e.wheelDelta / 120;
@@ -220,10 +224,13 @@ define(
* @param {Object} e 事件参数
*/
function mouseover(e) {
prevent(e);
if(false === this.events.mouseover) {
return;
}
prevent(e);
this.fire('over');
}
@@ -233,10 +240,13 @@ define(
* @param {Object} e 事件参数
*/
function mouseout(e) {
prevent(e);
if(false === this.events.mouseout) {
return;
}
prevent(e);
this.fire('out');
}

View File

@@ -12,11 +12,39 @@
<button data-action="new" type="button" class="btn btn-primary btn-sm">新建</button>
<button data-action="open" type="button" class="btn btn-primary btn-sm">打开</button>
<button data-action="import" type="button" class="btn btn-primary btn-sm">导入</button>
<a id="export-btn" href="javascript:void(0)" data-action="export" data-type="ttf" class="btn btn-primary btn-sm">导出ttf</a>
<a id="export-btn-woff" href="javascript:void(0)" data-action="export" data-type="woff" class="btn btn-primary btn-sm">导出woff</a>
<a id="export-btn-svg" href="javascript:void(0)" data-action="export" data-type="svg" class="btn btn-primary btn-sm">导出svg</a>
<button data-action="save" type="button" class="btn btn-primary btn-sm">保存</button>
<button data-action="setting" type="button" class="btn btn-primary btn-sm">设置</button>
<div class="btn-group">
<button type="button" class="btn btn-primary btn-sm dropdown-toggle" data-toggle="dropdown">
插入
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li data-action="add-new"><a>新字形</a></li>
<li data-action="add-exist"><a>已有字形</a></li>
</ul>
</div>
<a id="export-btn" href="#" data-action="export" data-type="ttf" class="btn btn-success btn-sm">导出ttf</a>
<a id="export-btn-woff" href="#" data-action="export" data-type="woff" class="btn btn-success btn-sm">导出woff</a>
<a id="export-btn-svg" href="#" data-action="export" data-type="svg" class="btn btn-success btn-sm">导出svg</a>
<button data-action="save" type="button" class="btn btn-warning btn-sm">保存项目</button>
<div class="btn-group">
<button type="button" class="btn btn-info btn-sm dropdown-toggle" data-toggle="dropdown">
设置
<span class="caret"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li><a data-action="setting-unicode">代码点</a></li>
<li><a>字体信息</a></li>
<li><a>字形转换</a></li>
</ul>
</div>
</section>
<section class="sidebar">
@@ -31,8 +59,27 @@
</div>
</section>
<div id="selection-range" class="selection-range"></div>
<div id="loading" class="loading">正在加载...</div>
<!-- Modal -->
<div class="modal" id="model-dialog" tabindex="-1" role="dialog" aria-labelledby="model-label" aria-hidden="true" data-backdrop="false">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">&times;</span><span class="sr-only">关闭</span></button>
<h4 class="modal-title" id="model-label">设置代码点</h4>
</div>
<div class="modal-body"></div>
<div class="modal-footer">
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">取消</button>
<button type="button" class="btn btn-primary btn-sm btn-confirm">确定</button>
</div>
</div>
</div>
</div>
<script src="./dep/esl.js"></script>
<script src="./dep/jquery.min.js"></script>
<script src="./dep/bootstrap/js/bootstrap.min.js"></script>
@@ -47,6 +94,6 @@
define('jquery', $);
require(['fonteditor/ttf/main'])
</script>
<form id="font-form"><input id="font-import" type="file"></form>
<form id="font-form" style="width:0px;height:0px;overflow:hidden;"><input id="font-import" type="file"></form>
</body>
</html>