Рефакторинг
This commit is contained in:
@@ -228,28 +228,31 @@ class TextPage extends Vue {
|
||||
|
||||
//parsed
|
||||
if (this.parsed) {
|
||||
this.parsed.p = this.p;
|
||||
this.parsed.w = this.w;// px, ширина текста
|
||||
this.parsed.font = this.font;
|
||||
this.parsed.fontSize = this.fontSize;
|
||||
this.parsed.wordWrap = this.wordWrap;
|
||||
this.parsed.cutEmptyParagraphs = this.cutEmptyParagraphs;
|
||||
this.parsed.addEmptyParagraphs = this.addEmptyParagraphs;
|
||||
let t = wideLetter;
|
||||
if (!this.drawHelper.measureText(t, {}))
|
||||
throw new Error('Ошибка measureText');
|
||||
while (this.drawHelper.measureText(t, {}) < this.w) t += wideLetter;
|
||||
this.parsed.maxWordLength = t.length - 1;
|
||||
this.parsed.measureText = this.drawHelper.measureText.bind(this.drawHelper);
|
||||
this.parsed.lineHeight = this.lineHeight;
|
||||
this.parsed.showImages = this.showImages;
|
||||
this.parsed.showInlineImagesInCenter = this.showInlineImagesInCenter;
|
||||
this.parsed.imageHeightLines = this.imageHeightLines;
|
||||
this.parsed.imageFitWidth = this.imageFitWidth;
|
||||
this.parsed.compactTextPerc = this.compactTextPerc;
|
||||
this.testText = 'Это тестовый текст. Его ширина выдается системой неправильно некоторое время.';
|
||||
|
||||
this.parsed.testText = 'Это тестовый текст. Его ширина выдается системой неверно некоторое время.';
|
||||
this.parsed.testWidth = this.drawHelper.measureText(this.parsed.testText, {});
|
||||
let wideLine = wideLetter;
|
||||
if (!this.drawHelper.measureText(wideLine, {}))
|
||||
throw new Error('Ошибка measureText');
|
||||
while (this.drawHelper.measureText(wideLine, {}) < this.w) wideLine += wideLetter;
|
||||
|
||||
this.parsed.setSettings({
|
||||
p: this.p,
|
||||
w: this.w,
|
||||
font: this.font,
|
||||
fontSize: this.fontSize,
|
||||
wordWrap: this.wordWrap,
|
||||
cutEmptyParagraphs: this.cutEmptyParagraphs,
|
||||
addEmptyParagraphs: this.addEmptyParagraphs,
|
||||
maxWordLength: wideLine.length - 1,
|
||||
lineHeight: this.lineHeight,
|
||||
showImages: this.showImages,
|
||||
showInlineImagesInCenter: this.showInlineImagesInCenter,
|
||||
imageHeightLines: this.imageHeightLines,
|
||||
imageFitWidth: this.imageFitWidth,
|
||||
compactTextPerc: this.compactTextPerc,
|
||||
testWidth: this.drawHelper.measureText(this.testText, {}),
|
||||
measureText: this.drawHelper.measureText.bind(this.drawHelper),
|
||||
});
|
||||
}
|
||||
|
||||
//scrolling page
|
||||
@@ -333,19 +336,25 @@ class TextPage extends Vue {
|
||||
if (!omitLoadFonts)
|
||||
await this.loadFonts();
|
||||
|
||||
this.draw();
|
||||
|
||||
// ширина шрифта некоторое время выдается неверно, поэтому
|
||||
if (!omitLoadFonts) {
|
||||
if (omitLoadFonts) {
|
||||
this.draw();
|
||||
} else {
|
||||
// ширина шрифта некоторое время выдается неверно,
|
||||
// не получилось событийно отловить этот момент, поэтому костыль
|
||||
const parsed = this.parsed;
|
||||
|
||||
let i = 0;
|
||||
const t = this.parsed.testText;
|
||||
while (i++ < 50 && this.parsed === parsed && this.drawHelper.measureText(t, {}) === this.parsed.testWidth)
|
||||
const t = this.testText;
|
||||
const tw = this.drawHelper.measureText(t, {});
|
||||
//5 секунд проверяем изменения шрифта
|
||||
while (i++ < 50 && this.parsed === parsed && this.drawHelper.measureText(t, {}) === tw) {
|
||||
if (i == 10) //через 1 сек
|
||||
this.draw();
|
||||
await utils.sleep(100);
|
||||
}
|
||||
|
||||
if (this.parsed === parsed) {
|
||||
this.parsed.testWidth = this.drawHelper.measureText(t, {});
|
||||
this.parsed.setSettings({testWidth: this.drawHelper.measureText(t, {})});
|
||||
this.draw();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,23 +4,44 @@ import * as utils from '../../../share/utils';
|
||||
|
||||
const maxImageLineCount = 100;
|
||||
|
||||
// defaults
|
||||
const defaultSettings = {
|
||||
p: 30, //px, отступ параграфа
|
||||
w: 500, //px, ширина страницы
|
||||
|
||||
font: '', //css описание шрифта
|
||||
fontSize: 20, //px, размер шрифта
|
||||
wordWrap: false, //перенос по слогам
|
||||
cutEmptyParagraphs: false, //убирать пустые параграфы
|
||||
addEmptyParagraphs: 0, //добавлять n пустых параграфов перед непустым
|
||||
maxWordLength: 500, //px, максимальная длина слова без пробелов
|
||||
lineHeight: 26, //px, высота строки
|
||||
showImages: true, //показыввать изображения
|
||||
showInlineImagesInCenter: true, //выносить изображения в центр, работает на этапе первичного парсинга (parse)
|
||||
imageHeightLines: 100, //кол-во строк, максимальная высота изображения
|
||||
imageFitWidth: true, //ширина изображения не более ширины страницы
|
||||
compactTextPerc: 0, //проценты, степень компактности текста
|
||||
testWidth: 0, //ширина тестовой строки, пересчитывается извне при изменении шрифта браузером
|
||||
|
||||
//заглушка, измеритель ширины текста
|
||||
measureText: (text, style) => {// eslint-disable-line no-unused-vars
|
||||
return text.length*20;
|
||||
},
|
||||
};
|
||||
|
||||
export default class BookParser {
|
||||
constructor(settings) {
|
||||
if (settings) {
|
||||
this.showInlineImagesInCenter = settings.showInlineImagesInCenter;
|
||||
}
|
||||
constructor(settings = {}) {
|
||||
this.sets = {};
|
||||
|
||||
// defaults
|
||||
this.p = 30;// px, отступ параграфа
|
||||
this.w = 300;// px, ширина страницы
|
||||
this.wordWrap = false;// перенос по слогам
|
||||
|
||||
//заглушка
|
||||
this.measureText = (text, style) => {// eslint-disable-line no-unused-vars
|
||||
return text.length*20;
|
||||
};
|
||||
this.setSettings(defaultSettings);
|
||||
this.setSettings(settings);
|
||||
}
|
||||
|
||||
setSettings(settings = {}) {
|
||||
this.sets = Object.assign({}, this.sets, settings);
|
||||
this.measureText = this.sets.measureText;
|
||||
}
|
||||
|
||||
async parse(data, callback) {
|
||||
if (!callback)
|
||||
callback = () => {};
|
||||
@@ -210,14 +231,14 @@ export default class BookParser {
|
||||
if (href[0] == '#') {//local
|
||||
imageNum++;
|
||||
|
||||
if (inPara && !this.showInlineImagesInCenter && !center)
|
||||
if (inPara && !this.sets.showInlineImagesInCenter && !center)
|
||||
growParagraph(`<image-inline href="${href}" num="${imageNum}"></image-inline>`, 0);
|
||||
else
|
||||
newParagraph(`<image href="${href}" num="${imageNum}">${' '.repeat(maxImageLineCount)}</image>`, maxImageLineCount);
|
||||
|
||||
this.images.push({paraIndex, num: imageNum, id, local, alt});
|
||||
|
||||
if (inPara && this.showInlineImagesInCenter)
|
||||
if (inPara && this.sets.showInlineImagesInCenter)
|
||||
newParagraph(' ', 1);
|
||||
} else {//external
|
||||
imageNum++;
|
||||
@@ -632,7 +653,7 @@ export default class BookParser {
|
||||
});
|
||||
|
||||
//длинные слова (или белиберду без пробелов) тоже разобьем
|
||||
const maxWordLength = this.maxWordLength;
|
||||
const maxWordLength = this.sets.maxWordLength;
|
||||
const parts = result;
|
||||
result = [];
|
||||
for (const part of parts) {
|
||||
@@ -712,37 +733,43 @@ export default class BookParser {
|
||||
|
||||
parsePara(paraIndex) {
|
||||
const para = this.para[paraIndex];
|
||||
const s = this.sets;
|
||||
|
||||
//перераспарсиваем только при изменении одного из параметров
|
||||
if (!this.force &&
|
||||
para.parsed &&
|
||||
para.parsed.testWidth === this.testWidth &&
|
||||
para.parsed.w === this.w &&
|
||||
para.parsed.p === this.p &&
|
||||
para.parsed.wordWrap === this.wordWrap &&
|
||||
para.parsed.maxWordLength === this.maxWordLength &&
|
||||
para.parsed.font === this.font &&
|
||||
para.parsed.cutEmptyParagraphs === this.cutEmptyParagraphs &&
|
||||
para.parsed.addEmptyParagraphs === this.addEmptyParagraphs &&
|
||||
para.parsed.showImages === this.showImages &&
|
||||
para.parsed.imageHeightLines === this.imageHeightLines &&
|
||||
para.parsed.imageFitWidth === this.imageFitWidth &&
|
||||
para.parsed.compactTextPerc === this.compactTextPerc
|
||||
para.parsed.p === s.p &&
|
||||
para.parsed.w === s.w &&
|
||||
para.parsed.font === s.font &&
|
||||
para.parsed.fontSize === s.fontSize &&
|
||||
para.parsed.wordWrap === s.wordWrap &&
|
||||
para.parsed.cutEmptyParagraphs === s.cutEmptyParagraphs &&
|
||||
para.parsed.addEmptyParagraphs === s.addEmptyParagraphs &&
|
||||
para.parsed.maxWordLength === s.maxWordLength &&
|
||||
para.parsed.lineHeight === s.lineHeight &&
|
||||
para.parsed.showImages === s.showImages &&
|
||||
para.parsed.imageHeightLines === s.imageHeightLines &&
|
||||
para.parsed.imageFitWidth === s.imageFitWidth &&
|
||||
para.parsed.compactTextPerc === s.compactTextPerc &&
|
||||
para.parsed.testWidth === s.testWidth
|
||||
)
|
||||
return para.parsed;
|
||||
|
||||
const parsed = {
|
||||
testWidth: this.testWidth,
|
||||
w: this.w,
|
||||
p: this.p,
|
||||
wordWrap: this.wordWrap,
|
||||
maxWordLength: this.maxWordLength,
|
||||
font: this.font,
|
||||
cutEmptyParagraphs: this.cutEmptyParagraphs,
|
||||
addEmptyParagraphs: this.addEmptyParagraphs,
|
||||
showImages: this.showImages,
|
||||
imageHeightLines: this.imageHeightLines,
|
||||
imageFitWidth: this.imageFitWidth,
|
||||
compactTextPerc: this.compactTextPerc,
|
||||
p: s.p,
|
||||
w: s.w,
|
||||
font: s.font,
|
||||
fontSize: s.fontSize,
|
||||
wordWrap: s.wordWrap,
|
||||
cutEmptyParagraphs: s.cutEmptyParagraphs,
|
||||
addEmptyParagraphs: s.addEmptyParagraphs,
|
||||
maxWordLength: s.maxWordLength,
|
||||
lineHeight: s.lineHeight,
|
||||
showImages: s.showImages,
|
||||
imageHeightLines: s.imageHeightLines,
|
||||
imageFitWidth: s.imageFitWidth,
|
||||
compactTextPerc: s.compactTextPerc,
|
||||
testWidth: s.testWidth,
|
||||
visible: true, //вычисляется позже
|
||||
};
|
||||
|
||||
@@ -774,7 +801,7 @@ export default class BookParser {
|
||||
let ofs = 0;//смещение от начала параграфа para.offset
|
||||
let imgW = 0;
|
||||
let imageInPara = false;
|
||||
const compactWidth = this.measureText('W', {})*this.compactTextPerc/100;
|
||||
const compactWidth = this.measureText('W', {})*parsed.compactTextPerc/100;
|
||||
// тут начинается самый замес, перенос по слогам и стилизация, а также изображения
|
||||
for (const part of parts) {
|
||||
style = part.style;
|
||||
@@ -787,14 +814,14 @@ export default class BookParser {
|
||||
if (!bin)
|
||||
bin = {h: 1, w: 1};
|
||||
|
||||
let lineCount = this.imageHeightLines;
|
||||
let c = Math.ceil(bin.h/this.lineHeight);
|
||||
let lineCount = parsed.imageHeightLines;
|
||||
let c = Math.ceil(bin.h/parsed.lineHeight);
|
||||
|
||||
const maxH = lineCount*this.lineHeight;
|
||||
const maxH = lineCount*parsed.lineHeight;
|
||||
let maxH2 = maxH;
|
||||
if (this.imageFitWidth && bin.w > this.w) {
|
||||
if (parsed.imageFitWidth && bin.w > this.w) {
|
||||
maxH2 = bin.h*this.w/bin.w;
|
||||
c = Math.ceil(maxH2/this.lineHeight);
|
||||
c = Math.ceil(maxH2/parsed.lineHeight);
|
||||
}
|
||||
lineCount = (c < lineCount ? c : lineCount);
|
||||
|
||||
@@ -834,10 +861,10 @@ export default class BookParser {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (part.image.id && part.image.inline && this.showImages) {
|
||||
if (part.image.id && part.image.inline && parsed.showImages) {
|
||||
const bin = this.binary[part.image.id];
|
||||
if (bin) {
|
||||
let imgH = (bin.h > this.fontSize ? this.fontSize : bin.h);
|
||||
let imgH = (bin.h > parsed.fontSize ? parsed.fontSize : bin.h);
|
||||
imgW += bin.w*imgH/bin.h;
|
||||
line.parts.push({style, text: '',
|
||||
image: {local: part.image.local, inline: true, id: part.image.id, num: part.image.num}});
|
||||
@@ -952,11 +979,11 @@ export default class BookParser {
|
||||
|
||||
//parsed.visible
|
||||
if (imageInPara) {
|
||||
parsed.visible = this.showImages;
|
||||
parsed.visible = parsed.showImages;
|
||||
} else {
|
||||
parsed.visible = !(
|
||||
(para.addIndex > this.addEmptyParagraphs) ||
|
||||
(para.addIndex == 0 && this.cutEmptyParagraphs && paragraphText.trim() == '')
|
||||
(para.addIndex > parsed.addEmptyParagraphs) ||
|
||||
(para.addIndex == 0 && parsed.cutEmptyParagraphs && paragraphText.trim() == '')
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user