Update ODT handling of font
This commit is contained in:
@@ -36,7 +36,6 @@ from time import time
|
|||||||
from PyQt5.QtCore import QCoreApplication, QRegularExpression
|
from PyQt5.QtCore import QCoreApplication, QRegularExpression
|
||||||
from PyQt5.QtGui import QFont
|
from PyQt5.QtGui import QFont
|
||||||
|
|
||||||
from novelwriter import CONFIG
|
|
||||||
from novelwriter.common import checkInt, formatTimeStamp, numberToRoman
|
from novelwriter.common import checkInt, formatTimeStamp, numberToRoman
|
||||||
from novelwriter.constants import (
|
from novelwriter.constants import (
|
||||||
nwHeadFmt, nwKeyWords, nwLabels, nwRegEx, nwShortcode, nwUnicode, trConst
|
nwHeadFmt, nwKeyWords, nwLabels, nwRegEx, nwShortcode, nwUnicode, trConst
|
||||||
@@ -141,7 +140,7 @@ class Tokenizer(ABC):
|
|||||||
self._markdown: list[str] = []
|
self._markdown: list[str] = []
|
||||||
|
|
||||||
# User Settings
|
# User Settings
|
||||||
self._textFont = CONFIG.textFont # Output text font
|
self._textFont = QFont("Serif", 11) # Output text font
|
||||||
self._lineHeight = 1.15 # Line height in units of em
|
self._lineHeight = 1.15 # Line height in units of em
|
||||||
self._blockIndent = 4.00 # Block indent in units of em
|
self._blockIndent = 4.00 # Block indent in units of em
|
||||||
self._firstIndent = False # Enable first line indent
|
self._firstIndent = False # Enable first line indent
|
||||||
|
|||||||
+58
-38
@@ -35,11 +35,14 @@ from hashlib import sha256
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from zipfile import ZipFile
|
from zipfile import ZipFile
|
||||||
|
|
||||||
|
from PyQt5.QtGui import QFont
|
||||||
|
|
||||||
from novelwriter import __version__
|
from novelwriter import __version__
|
||||||
from novelwriter.common import xmlIndent
|
from novelwriter.common import xmlIndent
|
||||||
from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels
|
from novelwriter.constants import nwHeadFmt, nwKeyWords, nwLabels
|
||||||
from novelwriter.core.project import NWProject
|
from novelwriter.core.project import NWProject
|
||||||
from novelwriter.core.tokenizer import T_Formats, Tokenizer, stripEscape
|
from novelwriter.core.tokenizer import T_Formats, Tokenizer, stripEscape
|
||||||
|
from novelwriter.types import FONT_WEIGHTS
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@@ -108,6 +111,10 @@ S_TEXT = "Text_20_body"
|
|||||||
S_META = "Text_20_Meta"
|
S_META = "Text_20_Meta"
|
||||||
S_HNF = "Header_20_and_20_Footer"
|
S_HNF = "Header_20_and_20_Footer"
|
||||||
|
|
||||||
|
# Font Data
|
||||||
|
FONT_WEIGHT_NUM = ["100", "200", "300", "400", "500", "600", "700", "800", "900"]
|
||||||
|
FONT_WEIGHT_MAP = {"400": "normal", "700": "bold"}
|
||||||
|
|
||||||
|
|
||||||
class ToOdt(Tokenizer):
|
class ToOdt(Tokenizer):
|
||||||
"""Core: Open Document Writer
|
"""Core: Open Document Writer
|
||||||
@@ -149,16 +156,17 @@ class ToOdt(Tokenizer):
|
|||||||
self._errData = [] # List of errors encountered
|
self._errData = [] # List of errors encountered
|
||||||
|
|
||||||
# Properties
|
# Properties
|
||||||
self._textFont = "Liberation Serif"
|
self._textFont = QFont("Liberation Serif", 12)
|
||||||
self._textSize = 12
|
|
||||||
self._textFixed = False
|
|
||||||
self._colourHead = False
|
self._colourHead = False
|
||||||
self._headerFormat = ""
|
self._headerFormat = ""
|
||||||
self._pageOffset = 0
|
self._pageOffset = 0
|
||||||
|
|
||||||
# Internal
|
# Internal
|
||||||
self._fontFamily = "'Liberation Serif'"
|
self._fontFamily = "Liberation Serif"
|
||||||
|
self._fontSize = 12
|
||||||
|
self._fontWeight = "normal"
|
||||||
self._fontPitch = "variable"
|
self._fontPitch = "variable"
|
||||||
|
self._fontBold = "bold"
|
||||||
self._fSizeTitle = "30pt"
|
self._fSizeTitle = "30pt"
|
||||||
self._fSizeHead1 = "24pt"
|
self._fSizeHead1 = "24pt"
|
||||||
self._fSizeHead2 = "20pt"
|
self._fSizeHead2 = "20pt"
|
||||||
@@ -260,19 +268,24 @@ class ToOdt(Tokenizer):
|
|||||||
# Initialise Variables
|
# Initialise Variables
|
||||||
# ====================
|
# ====================
|
||||||
|
|
||||||
self._fontFamily = self._textFont
|
intWeight = FONT_WEIGHTS.get(self._textFont.weight(), 400)
|
||||||
if len(self._textFont.split()) > 1:
|
fontWeight = str(intWeight)
|
||||||
self._fontFamily = f"'{self._textFont}'"
|
fontBold = str(min(intWeight + 300, 900))
|
||||||
self._fontPitch = "fixed" if self._textFixed else "variable"
|
|
||||||
|
|
||||||
self._fSizeTitle = f"{round(2.50 * self._textSize):d}pt"
|
self._fontFamily = self._textFont.family()
|
||||||
self._fSizeHead1 = f"{round(2.00 * self._textSize):d}pt"
|
self._fontSize = self._textFont.pointSize()
|
||||||
self._fSizeHead2 = f"{round(1.60 * self._textSize):d}pt"
|
self._fontWeight = FONT_WEIGHT_MAP.get(fontWeight, fontWeight)
|
||||||
self._fSizeHead3 = f"{round(1.30 * self._textSize):d}pt"
|
self._fontPitch = "fixed" if self._textFont.fixedPitch() else "variable"
|
||||||
self._fSizeHead4 = f"{round(1.15 * self._textSize):d}pt"
|
self._fontBold = FONT_WEIGHT_MAP.get(fontBold, fontBold)
|
||||||
self._fSizeHead = f"{round(1.15 * self._textSize):d}pt"
|
|
||||||
self._fSizeText = f"{self._textSize:d}pt"
|
self._fSizeTitle = f"{round(2.50 * self._fontSize):d}pt"
|
||||||
self._fSizeFoot = f"{round(0.8*self._textSize):d}pt"
|
self._fSizeHead1 = f"{round(2.00 * self._fontSize):d}pt"
|
||||||
|
self._fSizeHead2 = f"{round(1.60 * self._fontSize):d}pt"
|
||||||
|
self._fSizeHead3 = f"{round(1.30 * self._fontSize):d}pt"
|
||||||
|
self._fSizeHead4 = f"{round(1.15 * self._fontSize):d}pt"
|
||||||
|
self._fSizeHead = f"{round(1.15 * self._fontSize):d}pt"
|
||||||
|
self._fSizeText = f"{self._fontSize:d}pt"
|
||||||
|
self._fSizeFoot = f"{round(0.8*self._fontSize):d}pt"
|
||||||
|
|
||||||
mScale = self._lineHeight/1.15
|
mScale = self._lineHeight/1.15
|
||||||
|
|
||||||
@@ -320,8 +333,9 @@ class ToOdt(Tokenizer):
|
|||||||
tAttr[_mkTag("office", "version")] = X_VERS
|
tAttr[_mkTag("office", "version")] = X_VERS
|
||||||
|
|
||||||
fAttr = {}
|
fAttr = {}
|
||||||
fAttr[_mkTag("style", "name")] = self._textFont
|
fAttr[_mkTag("style", "name")] = self._fontFamily
|
||||||
fAttr[_mkTag("style", "font-pitch")] = self._fontPitch
|
fAttr[_mkTag("style", "font-pitch")] = self._fontPitch
|
||||||
|
fAttr[_mkTag("style", "font-weight")] = self._fontWeight
|
||||||
|
|
||||||
if self._isFlat:
|
if self._isFlat:
|
||||||
|
|
||||||
@@ -726,7 +740,7 @@ class ToOdt(Tokenizer):
|
|||||||
|
|
||||||
style = ODTTextStyle(f"T{len(self._autoText)+1:d}")
|
style = ODTTextStyle(f"T{len(self._autoText)+1:d}")
|
||||||
if hFmt & X_BLD:
|
if hFmt & X_BLD:
|
||||||
style.setFontWeight("bold")
|
style.setFontWeight(self._fontBold)
|
||||||
if hFmt & X_ITA:
|
if hFmt & X_ITA:
|
||||||
style.setFontStyle("italic")
|
style.setFontStyle("italic")
|
||||||
if hFmt & X_DEL:
|
if hFmt & X_DEL:
|
||||||
@@ -764,7 +778,7 @@ class ToOdt(Tokenizer):
|
|||||||
|
|
||||||
def _emToCm(self, value: float) -> str:
|
def _emToCm(self, value: float) -> str:
|
||||||
"""Converts an em value to centimetres."""
|
"""Converts an em value to centimetres."""
|
||||||
return f"{value*2.54/72*self._textSize:.3f}cm"
|
return f"{value*2.54/72*self._fontSize:.3f}cm"
|
||||||
|
|
||||||
##
|
##
|
||||||
# Style Elements
|
# Style Elements
|
||||||
@@ -808,8 +822,9 @@ class ToOdt(Tokenizer):
|
|||||||
_mkTag("style", "writing-mode"): "page",
|
_mkTag("style", "writing-mode"): "page",
|
||||||
})
|
})
|
||||||
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
||||||
_mkTag("style", "font-name"): self._textFont,
|
_mkTag("style", "font-name"): self._fontFamily,
|
||||||
_mkTag("fo", "font-family"): self._fontFamily,
|
_mkTag("fo", "font-family"): self._fontFamily,
|
||||||
|
_mkTag("fo", "font-weight"): self._fontWeight,
|
||||||
_mkTag("fo", "font-size"): self._fSizeText,
|
_mkTag("fo", "font-size"): self._fSizeText,
|
||||||
_mkTag("fo", "language"): self._dLanguage,
|
_mkTag("fo", "language"): self._dLanguage,
|
||||||
_mkTag("fo", "country"): self._dCountry,
|
_mkTag("fo", "country"): self._dCountry,
|
||||||
@@ -822,8 +837,9 @@ class ToOdt(Tokenizer):
|
|||||||
_mkTag("style", "class"): "text",
|
_mkTag("style", "class"): "text",
|
||||||
})
|
})
|
||||||
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
||||||
_mkTag("style", "font-name"): self._textFont,
|
_mkTag("style", "font-name"): self._fontFamily,
|
||||||
_mkTag("fo", "font-family"): self._fontFamily,
|
_mkTag("fo", "font-family"): self._fontFamily,
|
||||||
|
_mkTag("fo", "font-weight"): self._fontWeight,
|
||||||
_mkTag("fo", "font-size"): self._fSizeText,
|
_mkTag("fo", "font-size"): self._fSizeText,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -841,8 +857,9 @@ class ToOdt(Tokenizer):
|
|||||||
_mkTag("fo", "keep-with-next"): "always",
|
_mkTag("fo", "keep-with-next"): "always",
|
||||||
})
|
})
|
||||||
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
ET.SubElement(xStyl, _mkTag("style", "text-properties"), attrib={
|
||||||
_mkTag("style", "font-name"): self._textFont,
|
_mkTag("style", "font-name"): self._fontFamily,
|
||||||
_mkTag("fo", "font-family"): self._fontFamily,
|
_mkTag("fo", "font-family"): self._fontFamily,
|
||||||
|
_mkTag("fo", "font-weight"): self._fontWeight,
|
||||||
_mkTag("fo", "font-size"): self._fSizeHead,
|
_mkTag("fo", "font-size"): self._fSizeHead,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -868,9 +885,10 @@ class ToOdt(Tokenizer):
|
|||||||
style.setMarginBottom(self._mBotText)
|
style.setMarginBottom(self._mBotText)
|
||||||
style.setLineHeight(self._fLineHeight)
|
style.setLineHeight(self._fLineHeight)
|
||||||
style.setTextAlign(self._textAlign)
|
style.setTextAlign(self._textAlign)
|
||||||
style.setFontName(self._textFont)
|
style.setFontName(self._fontFamily)
|
||||||
style.setFontFamily(self._fontFamily)
|
style.setFontFamily(self._fontFamily)
|
||||||
style.setFontSize(self._fSizeText)
|
style.setFontSize(self._fSizeText)
|
||||||
|
style.setFontWeight(self._fontWeight)
|
||||||
style.packXML(self._xStyl)
|
style.packXML(self._xStyl)
|
||||||
self._mainPara[style.name] = style
|
self._mainPara[style.name] = style
|
||||||
|
|
||||||
@@ -891,9 +909,10 @@ class ToOdt(Tokenizer):
|
|||||||
style.setMarginTop(self._mTopMeta)
|
style.setMarginTop(self._mTopMeta)
|
||||||
style.setMarginBottom(self._mBotMeta)
|
style.setMarginBottom(self._mBotMeta)
|
||||||
style.setLineHeight(self._fLineHeight)
|
style.setLineHeight(self._fLineHeight)
|
||||||
style.setFontName(self._textFont)
|
style.setFontName(self._fontFamily)
|
||||||
style.setFontFamily(self._fontFamily)
|
style.setFontFamily(self._fontFamily)
|
||||||
style.setFontSize(self._fSizeText)
|
style.setFontSize(self._fSizeText)
|
||||||
|
style.setFontWeight(self._fontWeight)
|
||||||
style.setColour(self._colMetaTx)
|
style.setColour(self._colMetaTx)
|
||||||
style.setOpacity(self._opaMetaTx)
|
style.setOpacity(self._opaMetaTx)
|
||||||
style.packXML(self._xStyl)
|
style.packXML(self._xStyl)
|
||||||
@@ -908,10 +927,10 @@ class ToOdt(Tokenizer):
|
|||||||
style.setMarginTop(self._mTopTitle)
|
style.setMarginTop(self._mTopTitle)
|
||||||
style.setMarginBottom(self._mBotTitle)
|
style.setMarginBottom(self._mBotTitle)
|
||||||
style.setTextAlign("center")
|
style.setTextAlign("center")
|
||||||
style.setFontName(self._textFont)
|
style.setFontName(self._fontFamily)
|
||||||
style.setFontFamily(self._fontFamily)
|
style.setFontFamily(self._fontFamily)
|
||||||
style.setFontSize(self._fSizeTitle)
|
style.setFontSize(self._fSizeTitle)
|
||||||
style.setFontWeight("bold")
|
style.setFontWeight(self._fontBold)
|
||||||
style.packXML(self._xStyl)
|
style.packXML(self._xStyl)
|
||||||
self._mainPara[style.name] = style
|
self._mainPara[style.name] = style
|
||||||
|
|
||||||
@@ -925,9 +944,10 @@ class ToOdt(Tokenizer):
|
|||||||
style.setMarginBottom(self._mBotText)
|
style.setMarginBottom(self._mBotText)
|
||||||
style.setLineHeight(self._fLineHeight)
|
style.setLineHeight(self._fLineHeight)
|
||||||
style.setTextAlign("center")
|
style.setTextAlign("center")
|
||||||
style.setFontName(self._textFont)
|
style.setFontName(self._fontFamily)
|
||||||
style.setFontFamily(self._fontFamily)
|
style.setFontFamily(self._fontFamily)
|
||||||
style.setFontSize(self._fSizeText)
|
style.setFontSize(self._fSizeText)
|
||||||
|
style.setFontWeight(self._fontWeight)
|
||||||
style.packXML(self._xStyl)
|
style.packXML(self._xStyl)
|
||||||
self._mainPara[style.name] = style
|
self._mainPara[style.name] = style
|
||||||
|
|
||||||
@@ -940,10 +960,10 @@ class ToOdt(Tokenizer):
|
|||||||
style.setClass("text")
|
style.setClass("text")
|
||||||
style.setMarginTop(self._mTopHead1)
|
style.setMarginTop(self._mTopHead1)
|
||||||
style.setMarginBottom(self._mBotHead1)
|
style.setMarginBottom(self._mBotHead1)
|
||||||
style.setFontName(self._textFont)
|
style.setFontName(self._fontFamily)
|
||||||
style.setFontFamily(self._fontFamily)
|
style.setFontFamily(self._fontFamily)
|
||||||
style.setFontSize(self._fSizeHead1)
|
style.setFontSize(self._fSizeHead1)
|
||||||
style.setFontWeight("bold")
|
style.setFontWeight(self._fontBold)
|
||||||
style.setColour(self._colHead12)
|
style.setColour(self._colHead12)
|
||||||
style.setOpacity(self._opaHead12)
|
style.setOpacity(self._opaHead12)
|
||||||
style.packXML(self._xStyl)
|
style.packXML(self._xStyl)
|
||||||
@@ -958,10 +978,10 @@ class ToOdt(Tokenizer):
|
|||||||
style.setClass("text")
|
style.setClass("text")
|
||||||
style.setMarginTop(self._mTopHead2)
|
style.setMarginTop(self._mTopHead2)
|
||||||
style.setMarginBottom(self._mBotHead2)
|
style.setMarginBottom(self._mBotHead2)
|
||||||
style.setFontName(self._textFont)
|
style.setFontName(self._fontFamily)
|
||||||
style.setFontFamily(self._fontFamily)
|
style.setFontFamily(self._fontFamily)
|
||||||
style.setFontSize(self._fSizeHead2)
|
style.setFontSize(self._fSizeHead2)
|
||||||
style.setFontWeight("bold")
|
style.setFontWeight(self._fontBold)
|
||||||
style.setColour(self._colHead12)
|
style.setColour(self._colHead12)
|
||||||
style.setOpacity(self._opaHead12)
|
style.setOpacity(self._opaHead12)
|
||||||
style.packXML(self._xStyl)
|
style.packXML(self._xStyl)
|
||||||
@@ -976,10 +996,10 @@ class ToOdt(Tokenizer):
|
|||||||
style.setClass("text")
|
style.setClass("text")
|
||||||
style.setMarginTop(self._mTopHead3)
|
style.setMarginTop(self._mTopHead3)
|
||||||
style.setMarginBottom(self._mBotHead3)
|
style.setMarginBottom(self._mBotHead3)
|
||||||
style.setFontName(self._textFont)
|
style.setFontName(self._fontFamily)
|
||||||
style.setFontFamily(self._fontFamily)
|
style.setFontFamily(self._fontFamily)
|
||||||
style.setFontSize(self._fSizeHead3)
|
style.setFontSize(self._fSizeHead3)
|
||||||
style.setFontWeight("bold")
|
style.setFontWeight(self._fontBold)
|
||||||
style.setColour(self._colHead34)
|
style.setColour(self._colHead34)
|
||||||
style.setOpacity(self._opaHead34)
|
style.setOpacity(self._opaHead34)
|
||||||
style.packXML(self._xStyl)
|
style.packXML(self._xStyl)
|
||||||
@@ -994,10 +1014,10 @@ class ToOdt(Tokenizer):
|
|||||||
style.setClass("text")
|
style.setClass("text")
|
||||||
style.setMarginTop(self._mTopHead4)
|
style.setMarginTop(self._mTopHead4)
|
||||||
style.setMarginBottom(self._mBotHead4)
|
style.setMarginBottom(self._mBotHead4)
|
||||||
style.setFontName(self._textFont)
|
style.setFontName(self._fontFamily)
|
||||||
style.setFontFamily(self._fontFamily)
|
style.setFontFamily(self._fontFamily)
|
||||||
style.setFontSize(self._fSizeHead4)
|
style.setFontSize(self._fSizeHead4)
|
||||||
style.setFontWeight("bold")
|
style.setFontWeight(self._fontBold)
|
||||||
style.setColour(self._colHead34)
|
style.setColour(self._colHead34)
|
||||||
style.setOpacity(self._opaHead34)
|
style.setOpacity(self._opaHead34)
|
||||||
style.packXML(self._xStyl)
|
style.packXML(self._xStyl)
|
||||||
@@ -1077,7 +1097,7 @@ class ODTParagraphStyle:
|
|||||||
VALID_BREAK = ["auto", "column", "page", "even-page", "odd-page", "inherit"]
|
VALID_BREAK = ["auto", "column", "page", "even-page", "odd-page", "inherit"]
|
||||||
VALID_LEVEL = ["1", "2", "3", "4"]
|
VALID_LEVEL = ["1", "2", "3", "4"]
|
||||||
VALID_CLASS = ["text", "chapter", "extra"]
|
VALID_CLASS = ["text", "chapter", "extra"]
|
||||||
VALID_WEIGHT = ["normal", "inherit", "bold"]
|
VALID_WEIGHT = ["normal", "bold"] + FONT_WEIGHT_NUM
|
||||||
|
|
||||||
def __init__(self, name: str) -> None:
|
def __init__(self, name: str) -> None:
|
||||||
|
|
||||||
@@ -1320,8 +1340,8 @@ class ODTTextStyle:
|
|||||||
Only the used settings are exposed here to keep the class minimal
|
Only the used settings are exposed here to keep the class minimal
|
||||||
and fast.
|
and fast.
|
||||||
"""
|
"""
|
||||||
VALID_WEIGHT = ["normal", "inherit", "bold"]
|
VALID_WEIGHT = ["normal", "bold"] + FONT_WEIGHT_NUM
|
||||||
VALID_STYLE = ["normal", "inherit", "italic"]
|
VALID_STYLE = ["normal", "italic", "oblique"]
|
||||||
VALID_POS = ["super", "sub"]
|
VALID_POS = ["super", "sub"]
|
||||||
VALID_LSTYLE = ["none", "solid"]
|
VALID_LSTYLE = ["none", "solid"]
|
||||||
VALID_LTYPE = ["single", "double"]
|
VALID_LTYPE = ["single", "double"]
|
||||||
|
|||||||
Reference in New Issue
Block a user