A run of Unicode code points now needs one pair of carets, not one pair
each: ^9053 53EF 9053^ renders the characters adjacently, and a single
character inside such a run stands for itself. An invalid code point is
an error naming the position that wrote it, rather than an apology
rendered into the finished document; noncharacters are refused alongside
surrogates; and a code point that lands on a Klammertext special is safe
through the re-reads that assemble a document. The character tables now
produce the precomposed form, so a diacritic written as ^a" and one typed
directly are the same text to a search or a copy-paste.
"kdesc -u" describes how to write a Unicode character, with tables of
glyphs beside the codes that produce them. It is new and not yet
complete: it predates the sequence form and the typeface klammer below.
A typeface and a style are no longer both called "font". A typeface is a
family resolved by name; a style code is the one letter naming a type
style. So @document takes :serif_typeface and its siblings, a table takes
:style, captions take :caption_style and :caption_size, the uniform scale
is :text_scale, and the command is "kdesc --typeface". This renames
arguments a document may already use; an old name is a located error
rather than a silent omission.
@typeface sets a passage in another typeface for the length of that
passage:
@typeface Noto Sans Egyptian Hieroglyphs | ^132AA 133CF^ :scale 1.5 @
Writing the klammer is the whole declaration -- the document resolves the
typeface, embeds it in what it produces, and carries its license along.
Two typefaces for scripts no text font covers now ship with Klammertext:
Noto Sans Egyptian Hieroglyphs and Noto Sans Cuneiform. Every typeface in
the distribution now carries its license file.
(from dev 61e598698891)
153 lines
5.8 KiB
Python
153 lines
5.8 KiB
Python
import sys
|
|
import os
|
|
_klammertext_home = os.environ.get('KLAMMERTEXT_HOME', os.path.expanduser('~/projects/klammertext/K'))
|
|
sys.path.append(os.path.join(_klammertext_home, 'sks/kutil'))
|
|
sys.path.append(os.path.join(_klammertext_home, 'sks/target'))
|
|
import re
|
|
import os
|
|
import shutil
|
|
import kutil
|
|
import html_util
|
|
import latex_util
|
|
import klammer_base
|
|
import image_cache
|
|
import pprint
|
|
from html_util import E
|
|
import sys
|
|
|
|
class Image(klammer_base.Klammer_base):
|
|
id = 0
|
|
def __init__(self, K, as_string=True, width=None):
|
|
super().__init__(K)
|
|
# pprint.pprint(self.__dict__)
|
|
# self.show()
|
|
# /dev/shm is a fast RAM-backed tmpfs on Linux; on macOS it does not
|
|
# exist, so fall back to the platform temp directory.
|
|
cache_dir = "/dev/shm"
|
|
if not os.path.isdir(cache_dir):
|
|
import tempfile
|
|
cache_dir = tempfile.gettempdir()
|
|
self.cache = image_cache.Image_cache(cache_dir, self.Image_search_path, verbose=False)
|
|
self.basename = klammer_base.unescape_ktesc(self.basename)
|
|
self.source, self.pwidth, self.pheight, self.file_error = self.cache.get(self.K_target, self.basename)
|
|
if self.file_error:
|
|
self.file_error_message = f'\nERROR: Image "{self.basename}" not found'
|
|
self.as_string = as_string
|
|
if width:
|
|
self.width = width
|
|
self.rel_image = None
|
|
self.rel_fraction = 1.0
|
|
if self.rel:
|
|
self.rel_image, self.rel_pwidth, self.rel_pheight, self.file_error = self.cache.get(self.K_target, self.rel)
|
|
self.rel_fraction = self.pwidth / self.rel_pwidth
|
|
|
|
if self.file_error:
|
|
self.file_error_message = f'\nERROR: Image "{self.rel}" (the :rel image) not found'
|
|
|
|
def html(self):
|
|
img_dir = f"{self.K_output_dir}/{self.K_output_basename}/{self.Image_output_dir}"
|
|
|
|
# output_dir = self.K_output_dir or "."
|
|
# input_basename = self.__dict__.get("K_input_name", "")
|
|
# input_basename = "/" + input_basename if input_basename else ""
|
|
# img_dir = f"{output_dir}/{self.image_output_dir}{input_basename}"
|
|
#print("img_dir:", img_dir)
|
|
|
|
if not os.path.exists(img_dir):
|
|
os.makedirs(img_dir)
|
|
if not os.path.exists(f"{img_dir}/{os.path.basename(self.source)}"):
|
|
shutil.copy2(self.source, img_dir)
|
|
|
|
# width, scale_x, scale_y = kutil.parse_length(
|
|
# "html",
|
|
# self.width if self.width != "none" else self.image_default_width)
|
|
|
|
scale_x, scale_y = 1, 1 # Old
|
|
|
|
result = E("img")
|
|
if self.id:
|
|
result.attr("id", self.id)
|
|
|
|
filename = f"{self.Image_output_dir}/{os.path.basename(self.source)}"
|
|
|
|
result.attr("src", filename).attr("alt", os.path.basename(filename))
|
|
#if self.width:
|
|
|
|
# kutil.msg("rel: " + str(self.rel_fraction))
|
|
|
|
length, value, ltype = kutil.parse_length("html", self.width, self.rel_fraction)
|
|
if ltype == "w":
|
|
percent = float(value) * 100
|
|
result.sty(f"width: {percent}%")
|
|
else:
|
|
result.attr("width", length)
|
|
|
|
if self.border:
|
|
result.cls("image_border")
|
|
|
|
# print(result)
|
|
|
|
#result.attr("style", f"width: {width}")
|
|
# if width and width != "none":
|
|
# result.attr("style", f"width: {width}")
|
|
# if width == "none":
|
|
# if scale_x:
|
|
# result.attr("style", "width: 0px;")
|
|
# result.attr("scale-x", scale_x)
|
|
# elif scale_y:
|
|
# result.attr("style", "height: 0px;")
|
|
# result.attr("scale-y", scale_y)
|
|
|
|
if self.file_error:
|
|
self.caption += self.file_error_message
|
|
|
|
result = html_util.add_caption(
|
|
result, "Figure", self.number, self.caption, self.caption_style,
|
|
self.hpos, self.caption_side, False, self.caption_size,
|
|
offset=self.offset)
|
|
|
|
result = E("div").body(result).cls("image_margin")
|
|
|
|
if self.as_string:
|
|
result = str(result) + "\n"
|
|
|
|
return result
|
|
|
|
|
|
def tex(self):
|
|
# kutil.msg(f"number: {self.number}")
|
|
#selfsource, width, height = self.cache.get(self.K_target, self.basename)
|
|
source = os.path.abspath(self.source)
|
|
#if self.abswidth != 0:
|
|
# width = f"{self.abswidth}\\paperwidth"
|
|
#if self.caption or self.number:
|
|
# width = "\\textwidth"
|
|
#else:
|
|
width = kutil.parse_length("tex", self.width, self.rel_fraction)[0]
|
|
width = re.sub("px", "pt", width)
|
|
#result = f'\\includegraphics[width={width}]{{{source}}}'
|
|
if self.number or self.caption:
|
|
result = f'\\includegraphics[width=\\textwidth]{{{source}}}'
|
|
if self.file_error:
|
|
self.caption += self.file_error_message
|
|
result = latex_util.add_caption(
|
|
result, "Figure", self.number, self.caption, width,
|
|
self.hpos, self.caption_side, offset=self.offset)
|
|
#result, "Figure", self.number, self.caption, self.hpos, self.caption_side,
|
|
#self.width, self.caption_side_center, self.vmargin, self.caption_margin)
|
|
else:
|
|
result = f'\\includegraphics[width={width}]{{{source}}}'
|
|
result = latex_util.caption_wrapper(result, self.hpos, offset=self.offset)
|
|
name = f"Reference-Figure-{Image.id}"
|
|
result = f"\\hypertarget{{{name}}}{{}}\\label{{Label-{name}}}\n{result}"
|
|
Image.id += 1
|
|
# \includegraphics (bare or inside a caption wrapper's minipage) is
|
|
# box material: it must sit in vertical mode or it is typeset beside
|
|
# any text it follows.
|
|
return latex_util.block(result)
|
|
|
|
|
|
# Better to cause an error; there's no good text substitute for an image
|
|
# def txt(self):
|
|
# return f"[Image: {self.basename}\nCaption: {self.caption}]"
|