diff --git a/client/components/Reader/TextPage/DrawHelper.js b/client/components/Reader/TextPage/DrawHelper.js
index 75030bb8..4a9e1520 100644
--- a/client/components/Reader/TextPage/DrawHelper.js
+++ b/client/components/Reader/TextPage/DrawHelper.js
@@ -3,6 +3,124 @@ export default class DrawHelper {
return `${size}px ${this.fontName}`;
}
+ fontByStyle(style) {
+ return `${style.italic ? 'italic' : this.fontStyle} ${style.bold ? 'bold' : this.fontWeight} ${this.fontSize}px ${this.fontName}`;
+ }
+
+ measureText(text, style) {// eslint-disable-line no-unused-vars
+ this.context.font = this.fontByStyle(style);
+ return this.context.measureText(text).width;
+ }
+
+ measureTextFont(text, font) {// eslint-disable-line no-unused-vars
+ this.context.font = font;
+ return this.context.measureText(text).width;
+ }
+
+ drawPage(lines) {
+ if (!this.lastBook || this.pageLineCount < 1 || !this.book || !lines || !this.parsed.textLength)
+ return '';
+
+ const spaceWidth = this.measureText(' ', {});
+
+ let out = `
`;
+
+ let len = lines.length;
+ len = (len > this.pageLineCount + 1 ? this.pageLineCount + 1 : len);
+
+ let y = this.fontSize*this.textShift;
+
+ for (let i = 0; i < len; i++) {
+ const line = lines[i];
+ /* line:
+ {
+ begin: Number,
+ end: Number,
+ first: Boolean,
+ last: Boolean,
+ parts: array of {
+ style: {bold: Boolean, italic: Boolean, center: Boolean}
+ text: String,
+ }
+ }*/
+
+ let indent = line.first ? this.p : 0;
+
+ let lineText = '';
+ let center = false;
+ let centerStyle = {};
+ for (const part of line.parts) {
+ lineText += part.text;
+ center = center || part.style.center;
+ if (part.style.center)
+ centerStyle = part.style;
+ }
+
+ let filled = false;
+ // если выравнивание по ширине включено
+ if (this.textAlignJustify && !line.last && !center) {
+ const words = lineText.split(' ');
+
+ if (words.length > 1) {
+ const spaceCount = words.length - 1;
+
+ const space = (this.w - line.width + spaceWidth*spaceCount)/spaceCount;
+
+ let x = indent;
+ for (const part of line.parts) {
+ const font = this.fontByStyle(part.style);
+ let partWords = part.text.split(' ');
+
+ for (let j = 0; j < partWords.length; j++) {
+ let f = font;
+ let style = part.style;
+ let word = partWords[j];
+ if (i == 0 && this.searching && word.toLowerCase().indexOf(this.needle) >= 0) {
+ style = Object.assign({}, part.style, {bold: true});
+ f = this.fontByStyle(style);
+ }
+ out += this.fillText(word, x, y, f);
+ x += this.measureText(word, style) + (j < partWords.length - 1 ? space : 0);
+ }
+ }
+ filled = true;
+ }
+ }
+
+ // просто выводим текст
+ if (!filled) {
+ let x = indent;
+ x = (center ? (this.w - this.measureText(lineText, centerStyle))/2 : x);
+ for (const part of line.parts) {
+ let font = this.fontByStyle(part.style);
+
+ if (i == 0 && this.searching) {//для поиска, разбивка по словам
+ let partWords = part.text.split(' ');
+ for (let j = 0; j < partWords.length; j++) {
+ let f = font;
+ let style = part.style;
+ let word = partWords[j];
+ if (word.toLowerCase().indexOf(this.needle) >= 0) {
+ style = Object.assign({}, part.style, {bold: true});
+ f = this.fontByStyle(style);
+ }
+ out += this.fillText(word, x, y, f);
+ x += this.measureText(word, style) + (j < partWords.length - 1 ? spaceWidth : 0);
+ }
+ } else {
+ out += this.fillText(part.text, x, y, font);
+ x += this.measureText(part.text, part.style);
+ }
+ }
+ }
+ y += this.lineHeight;
+ }
+
+ out += '
';
+ return out;
+ }
+
drawPercentBar(x, y, w, h, font, fontSize, bookPos, textLength) {
const pad = 3;
const fh = h - 2*pad;
diff --git a/client/components/Reader/TextPage/TextPage.vue b/client/components/Reader/TextPage/TextPage.vue
index b793222e..1b1b6a04 100644
--- a/client/components/Reader/TextPage/TextPage.vue
+++ b/client/components/Reader/TextPage/TextPage.vue
@@ -112,9 +112,9 @@ class TextPage extends Vue {
this.toggleLayout = !this.toggleLayout;
if (this.toggleLayout)
- this.page1 = this.drawPage(lines);
+ this.page1 = this.drawHelper.drawPage(lines);
else
- this.page2 = this.drawPage(lines);
+ this.page2 = this.drawHelper.drawPage(lines);
this.doPageTransition();
}, 10);
@@ -148,28 +148,7 @@ class TextPage extends Vue {
this.lineHeight = this.fontSize + this.lineInterval;
this.pageLineCount = 1 + Math.floor((this.h - this.fontSize)/this.lineHeight);
- if (this.parsed) {
- this.parsed.p = this.p;
- this.parsed.w = this.w;// px, ширина текста
- this.parsed.font = this.font;
- this.parsed.wordWrap = this.wordWrap;
- let t = '';
- while (this.measureText(t, {}) < this.w) t += 'Щ';
- this.parsed.maxWordLength = t.length - 1;
- this.parsed.measureText = this.measureText;
- }
-
- //сообщение "Загрузка шрифтов..."
- const flText = 'Загрузка шрифта...';
- this.$refs.fontsLoading.innerHTML = flText;
- const fontsLoadingStyle = this.$refs.fontsLoading.style;
- fontsLoadingStyle.position = 'absolute';
- fontsLoadingStyle.fontSize = this.fontSize + 'px';
- fontsLoadingStyle.top = (this.realHeight/2 - 2*this.fontSize) + 'px';
- fontsLoadingStyle.left = (this.realWidth - this.measureText(flText, {}))/2 + 'px';
-
//stuff
- this.statusBarColor = this.hex2rgba(this.textColor || '#000000', this.statusBarColorAlpha);
this.currentTransition = '';
this.pageChangeDirectionDown = true;
this.fontShift = this.fontVertShift/100;
@@ -178,17 +157,52 @@ class TextPage extends Vue {
//drawHelper
this.drawHelper.realWidth = this.realWidth;
this.drawHelper.realHeight = this.realHeight;
+ this.drawHelper.lastBook = this.lastBook;
+ this.drawHelper.book = this.book;
+ this.drawHelper.parsed = this.parsed;
+ this.drawHelper.pageLineCount = this.pageLineCount;
this.drawHelper.backgroundColor = this.backgroundColor;
this.drawHelper.statusBarColor = this.statusBarColor;
+ this.drawHelper.fontStyle = this.fontStyle;
+ this.drawHelper.fontWeight = this.fontWeight;
+ this.drawHelper.fontSize = this.fontSize;
this.drawHelper.fontName = this.fontName;
this.drawHelper.fontShift = this.fontShift;
- this.drawHelper.measureText = this.measureText;
- this.drawHelper.measureTextFont = this.measureTextFont;
+ this.drawHelper.textColor = this.textColor;
+ this.drawHelper.textShift = this.textShift;
+ this.drawHelper.p = this.p;
+ this.drawHelper.w = this.w;
+ this.drawHelper.textAlignJustify = this.textAlignJustify;
+ this.drawHelper.lineHeight = this.lineHeight;
+ this.drawHelper.context = this.context;
+ //сообщение "Загрузка шрифтов..."
+ const flText = 'Загрузка шрифта...';
+ this.$refs.fontsLoading.innerHTML = flText;
+ const fontsLoadingStyle = this.$refs.fontsLoading.style;
+ fontsLoadingStyle.position = 'absolute';
+ fontsLoadingStyle.fontSize = this.fontSize + 'px';
+ fontsLoadingStyle.top = (this.realHeight/2 - 2*this.fontSize) + 'px';
+ fontsLoadingStyle.left = (this.realWidth - this.drawHelper.measureText(flText, {}))/2 + 'px';
+
+ //parsed
+ if (this.parsed) {
+ this.parsed.p = this.p;
+ this.parsed.w = this.w;// px, ширина текста
+ this.parsed.font = this.font;
+ this.parsed.wordWrap = this.wordWrap;
+ let t = '';
+ while (this.drawHelper.measureText(t, {}) < this.w) t += 'Щ';
+ this.parsed.maxWordLength = t.length - 1;
+ this.parsed.measureText = this.drawHelper.measureText.bind(this.drawHelper);
+ }
+
+ //statusBar
this.$refs.statusBar.style.left = '0px';
this.$refs.statusBar.style.top = (this.statusBarTop ? 1 : this.realHeight - this.statusBarHeight) + 'px';
+ this.statusBarColor = this.hex2rgba(this.textColor || '#000000', this.statusBarColorAlpha);
this.statusBarClickable = this.drawHelper.statusBarClickable(this.statusBarTop, this.statusBarHeight);
//scrolling page
@@ -208,16 +222,6 @@ class TextPage extends Vue {
page2.style.left = this.indentLR + 'px';
}
- measureText(text, style) {// eslint-disable-line no-unused-vars
- this.context.font = this.fontByStyle(style);
- return this.context.measureText(text).width;
- }
-
- measureTextFont(text, font) {// eslint-disable-line no-unused-vars
- this.context.font = font;
- return this.context.measureText(text).width;
- }
-
async checkLoadedFonts() {
let loaded = await Promise.all(this.fontList.map(font => document.fonts.check(font)));
if (loaded.some(r => !r)) {
@@ -323,7 +327,6 @@ class TextPage extends Vue {
this.linesUp = null;
this.linesDown = null;
- this.searching = false;
this.statusBarMessage = '';
@@ -407,31 +410,27 @@ class TextPage extends Vue {
return `${this.fontStyle} ${this.fontWeight} ${this.fontSize}px ${this.fontName}`;
}
- fontByStyle(style) {
- return `${style.italic ? 'italic' : this.fontStyle} ${style.bold ? 'bold' : this.fontWeight} ${this.fontSize}px ${this.fontName}`;
- }
-
onScrollingTransitionEnd() {
if (this.resolveTransitionFinish)
this.resolveTransitionFinish();
}
startSearch(needle) {
- this.needle = '';
+ this.drawHelper.needle = '';
const words = needle.split(' ');
for (const word of words) {
if (word != '') {
- this.needle = word;
+ this.drawHelper.needle = word;
break;
}
}
- this.searching = true;
+ this.drawHelper.searching = true;
this.draw();
}
stopSearch() {
- this.searching = false;
+ this.drawHelper.searching = false;
this.draw();
}
@@ -508,7 +507,7 @@ class TextPage extends Vue {
const lines = this.getLines(this.bookPos);
this.linesDown = lines.linesDown;
this.linesUp = lines.linesUp;
- this.page1 = this.drawPage(lines.linesDown);
+ this.page1 = this.drawHelper.drawPage(lines.linesDown);
}
//caching next
@@ -518,7 +517,7 @@ class TextPage extends Vue {
if (this.linesDown && this.linesDown.length > this.pageLineCount && this.pageLineCount > 0) {
this.cachedPos = this.linesDown[1].begin;
this.linesCached = this.getLines(this.cachedPos);
- this.pageCached = this.drawPage(this.linesCached.linesDown);
+ this.pageCached = this.drawHelper.drawPage(this.linesCached.linesDown);
}
this.cachedPageTimer = null;
}, 20);
@@ -549,12 +548,6 @@ class TextPage extends Vue {
const lines = this.getLines(this.bookPos);
this.linesDown = lines.linesDown;
this.linesUp = lines.linesUp;
-
- /*if (this.toggleLayout)
- this.page1 = this.drawPage(lines.linesDown);
- else
- this.page2 = this.drawPage(lines.linesDown);*/
-
this.debouncedUpdatePage(lines.linesDown);
}
@@ -590,110 +583,6 @@ class TextPage extends Vue {
};
}
- drawPage(lines) {
- if (!this.lastBook || this.pageLineCount < 1 || !this.book || !lines || !this.parsed.textLength)
- return '';
-
- const spaceWidth = this.measureText(' ', {});
-
- let out = ``;
-
- let len = lines.length;
- len = (len > this.pageLineCount + 1 ? this.pageLineCount + 1 : len);
-
- let y = this.fontSize*this.textShift;
-
- for (let i = 0; i < len; i++) {
- const line = lines[i];
- /* line:
- {
- begin: Number,
- end: Number,
- first: Boolean,
- last: Boolean,
- parts: array of {
- style: {bold: Boolean, italic: Boolean, center: Boolean}
- text: String,
- }
- }*/
-
- let indent = line.first ? this.p : 0;
-
- let lineText = '';
- let center = false;
- let centerStyle = {};
- for (const part of line.parts) {
- lineText += part.text;
- center = center || part.style.center;
- if (part.style.center)
- centerStyle = part.style;
- }
-
- let filled = false;
- // если выравнивание по ширине включено
- if (this.textAlignJustify && !line.last && !center) {
- const words = lineText.split(' ');
-
- if (words.length > 1) {
- const spaceCount = words.length - 1;
-
- const space = (this.w - line.width + spaceWidth*spaceCount)/spaceCount;
-
- let x = indent;
- for (const part of line.parts) {
- const font = this.fontByStyle(part.style);
- let partWords = part.text.split(' ');
-
- for (let j = 0; j < partWords.length; j++) {
- let f = font;
- let style = part.style;
- let word = partWords[j];
- if (i == 0 && this.searching && word.toLowerCase().indexOf(this.needle) >= 0) {
- style = Object.assign({}, part.style, {bold: true});
- f = this.fontByStyle(style);
- }
- out += this.drawHelper.fillText(word, x, y, f);
- x += this.measureText(word, style) + (j < partWords.length - 1 ? space : 0);
- }
- }
- filled = true;
- }
- }
-
- // просто выводим текст
- if (!filled) {
- let x = indent;
- x = (center ? (this.w - this.measureText(lineText, centerStyle))/2 : x);
- for (const part of line.parts) {
- let font = this.fontByStyle(part.style);
-
- if (i == 0 && this.searching) {//для поиска, разбивка по словам
- let partWords = part.text.split(' ');
- for (let j = 0; j < partWords.length; j++) {
- let f = font;
- let style = part.style;
- let word = partWords[j];
- if (word.toLowerCase().indexOf(this.needle) >= 0) {
- style = Object.assign({}, part.style, {bold: true});
- f = this.fontByStyle(style);
- }
- out += this.drawHelper.fillText(word, x, y, f);
- x += this.measureText(word, style) + (j < partWords.length - 1 ? spaceWidth : 0);
- }
- } else {
- out += this.drawHelper.fillText(part.text, x, y, font);
- x += this.measureText(part.text, part.style);
- }
- }
- }
- y += this.lineHeight;
- }
-
- out += '
';
- return out;
- }
-
drawStatusBar(message) {
if (this.w < minLayoutWidth) {
this.statusBar = null;
@@ -790,9 +679,9 @@ class TextPage extends Vue {
this.linesUpNext = lines.linesUp;
if (this.toggleLayout)
- this.page2 = this.drawPage(lines.linesDown);//наоборот
+ this.page2 = this.drawHelper.drawPage(lines.linesDown);//наоборот
else
- this.page1 = this.drawPage(lines.linesDown);
+ this.page1 = this.drawHelper.drawPage(lines.linesDown);
this.pagePrepared = true;
}