Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kolaru compat with mathtexengine #1952

Merged
merged 28 commits into from
May 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
45485be
Use TeXChar common interface with FontExtent
Kolaru Mar 25, 2022
57f03db
Uniformize char and texchar with GlyphExtent
Kolaru Apr 19, 2022
283ab2f
Use TeXChar common interface with FontExtent
Kolaru Apr 19, 2022
e36aae3
Uniformize char and texchar with GlyphExtent
Kolaru Apr 19, 2022
299176e
Merge branch 'compat_with_mathtexengine' of https://github.com/Kolaru…
Kolaru Apr 19, 2022
1f4ccc3
Fix boundingbox for texchar
Kolaru Apr 20, 2022
c4c8f7b
Merge branch 'master' into compat_with_mathtexengine
ffreyer May 13, 2022
799476d
fix line position
ffreyer May 13, 2022
8f03716
fix @cell
ffreyer May 13, 2022
8236a5a
fix word wrap
ffreyer May 13, 2022
cec9dae
fix text bounding boxes
ffreyer May 13, 2022
e63080d
switch to ink_bounding_box
ffreyer May 13, 2022
13866bf
use character height instead of font height
ffreyer May 13, 2022
f9dfc09
tweak padding
ffreyer May 13, 2022
dbf59e2
Merge branch 'master' into compat_with_mathtexengine
SimonDanisch May 16, 2022
1ee9347
Merge branch 'master' into compat_with_mathtexengine
SimonDanisch May 17, 2022
6079966
Merge branch 'compat_with_mathtexengine' of https://github.com/Kolaru…
SimonDanisch May 18, 2022
cc84167
use height_insensitive_bb for chars
SimonDanisch May 18, 2022
54de463
revert to inkboundingbox for ink_bb
jkrumbiegel May 20, 2022
3859037
use height_insensitive_boundingbox_with_advance
jkrumbiegel May 20, 2022
4228de7
remove dead code
jkrumbiegel May 20, 2022
9580b87
improve test
jkrumbiegel May 20, 2022
dc8317b
use _with_advance everywhere
jkrumbiegel May 20, 2022
6857bf6
remove false namespacing
jkrumbiegel May 20, 2022
f957e6f
correct ascender / descender use in alignment
jkrumbiegel May 20, 2022
a1a7391
revert paddings
jkrumbiegel May 20, 2022
63abf38
Merge branch 'master' into Kolaru-compat_with_mathtexengine
jkrumbiegel May 20, 2022
9862b3c
remove now invalid test
jkrumbiegel May 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ KernelDensity = "0.5, 0.6"
LaTeXStrings = "1.2"
MakieCore = "0.3.1"
Match = "1.1"
MathTeXEngine = "0.2"
MathTeXEngine = "0.4"
Observables = "0.5.1"
OffsetArrays = "1"
Packing = "0.4"
Expand Down
2 changes: 1 addition & 1 deletion ReferenceTests/src/tests/text.jl
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ end
axis = (
title = L"\sum_k{x y_k}",
xlabel = L"\lim_{x →\infty} A^j v_{(a + b)_k}^i \sqrt{23.5} x!= \sqrt{\frac{1+6}{4+a+g}}\int_{0}^{2π} \sin(x) dx",
ylabel = L"x + y - sin(x) × tan(y) + \sqrt{2}",
ylabel = L"x + y - \sin(x) × \tan(y) + \sqrt{2}",
),
figure = (fontsize = 18,)
)
Expand Down
1 change: 1 addition & 0 deletions src/Makie.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ using GeometryBasics: widths, positive_widths, VecTypes, AbstractPolygon, value,
using Distributions: Distribution, VariateForm, Discrete, QQPair, pdf, quantile, qqbuild

import FileIO: save
import FreeTypeAbstraction: height_insensitive_boundingbox
using Printf: @sprintf
using StatsFuns: logit, logistic
# Imports from Base which we don't want to have to qualify
Expand Down
18 changes: 9 additions & 9 deletions src/basic_recipes/text.jl
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ function plot!(plot::Text{<:Tuple{<:Union{LaTeXString, AbstractVector{<:LaTeXStr
scene = Makie.parent_scene(plot)

onany(lineels_glyphcollection_offset, plot.position, scene.camera.projectionview
) do (allels, gcs, offs), pos, projview
) do (allels, gcs, offs), pos, _

if pos isa Vector && (length(pos) != length(allels))
return
Expand All @@ -147,7 +147,7 @@ function plot!(plot::Text{<:Tuple{<:Union{LaTeXString, AbstractVector{<:LaTeXStr
allels = [allels]
end
broadcast_foreach(allels, offs, pos, ts, rot) do allels, offs, pos, ts, rot
offset = Point2f(pos)
offset = project(scene.camera, :data, :pixel, Point2f(pos))[Vec(1, 2)]

els = map(allels) do el
el[1] isa VLine || el[1] isa HLine || return nothing
Expand Down Expand Up @@ -183,7 +183,7 @@ function plot!(plot::Text{<:Tuple{<:Union{LaTeXString, AbstractVector{<:LaTeXStr
linesegments!(
plot, linepairs, linewidth = linewidths, color = plot.color,
visible = plot.visible, inspectable = plot.inspectable,
transparent = plot.transparency
transparent = plot.transparency, space = :pixel
)

plot
Expand All @@ -202,13 +202,13 @@ function texelems_and_glyph_collection(str::LaTeXString, fontscale_px, halign, v

scales_2d = [Vec2f(x[3] * Vec2f(fs)) for x in els]

chars = [x[1].char for x in els]
fonts = [x[1].font for x in els]
texchars = [x[1] for x in els]
chars = [texchar.char for texchar in texchars]
fonts = [texchar.font for texchar in texchars]
extents = GlyphExtent.(texchars)

extents = [FreeTypeAbstraction.get_extent(f, c) for (f, c) in zip(fonts, chars)]

bboxes = map(extents, fonts, scales_2d) do ext, font, scale
unscaled_hi_bb = FreeTypeAbstraction.height_insensitive_boundingbox(ext, font)
bboxes = map(extents, scales_2d) do ext, scale
unscaled_hi_bb = height_insensitive_boundingbox_with_advance(ext)
return Rect2f(
origin(unscaled_hi_bb) * scale,
widths(unscaled_hi_bb) * scale
Expand Down
4 changes: 2 additions & 2 deletions src/interaction/inspector.jl
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,8 @@ end
function Bbox_from_glyphcollection(text, gc)
bbox = Rect2f(0, 0, 0, 0)
bboxes = Rect2f[]
broadcast_foreach(gc.extents, gc.fonts, gc.scales) do extent, font, scale
b = FreeTypeAbstraction.height_insensitive_boundingbox(extent, font) * scale
broadcast_foreach(gc.extents, gc.scales) do extent, scale
b = height_insensitive_boundingbox_with_advance(extent) * scale
push!(bboxes, b)
end
for (c, o, bb) in zip(text, gc.origins, bboxes)
Expand Down
36 changes: 19 additions & 17 deletions src/layouting/boundingbox.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
using FreeTypeAbstraction: height_insensitive_boundingbox

function parent_transform(x)
p = parent(transformation(x))
isnothing(p) ? Mat4f(I) : p.model[]
Expand All @@ -22,21 +20,29 @@ end

function gl_bboxes(gl::GlyphCollection)
scales = gl.scales.sv isa Vec2f ? (gl.scales.sv for _ in gl.extents) : gl.scales.sv
map(gl.extents, gl.fonts, scales) do ext, font, scale
unscaled_hi_bb = height_insensitive_boundingbox_with_advance(ext, font)
hi_bb = Rect2f(
Makie.origin(unscaled_hi_bb) * scale,
widths(unscaled_hi_bb) * scale
map(gl.extents, scales) do ext, scale
hi_bb = height_insensitive_boundingbox_with_advance(ext)
Rect2f(
Makie.origin(hi_bb) * scale,
widths(hi_bb) * scale
)
end
end

function height_insensitive_boundingbox_with_advance(ext, font)
function height_insensitive_boundingbox(ext::GlyphExtent)
l = ext.ink_bounding_box.origin[1]
w = ext.ink_bounding_box.widths[1]
b = ext.descender
h = ext.ascender
return Rect2f((l, b), (w, h - b))
end

function height_insensitive_boundingbox_with_advance(ext::GlyphExtent)
l = 0f0
r = FreeTypeAbstraction.hadvance(ext)
b = FreeTypeAbstraction.descender(font)
t = FreeTypeAbstraction.ascender(font)
return Rect2f((l, b), (r - l, t - b))
r = ext.hadvance
b = ext.descender
h = ext.ascender
return Rect2f((l, b), (r - l, h - b))
end

function boundingbox(glyphcollection::GlyphCollection, position::Point3f, rotation::Quaternion)
Expand All @@ -45,15 +51,11 @@ function boundingbox(glyphcollection::GlyphCollection, position::Point3f, rotati
return Rect3f(position, Vec3f(0, 0, 0))
end

chars = glyphcollection.glyphs
glyphorigins = glyphcollection.origins
glyphbbs = gl_bboxes(glyphcollection)

bb = Rect3f()
for (char, charo, glyphbb) in zip(chars, glyphorigins, glyphbbs)
# ignore line breaks
# char in ('\r', '\n') && continue

for (charo, glyphbb) in zip(glyphorigins, glyphbbs)
charbb = rotate_bbox(Rect3f(glyphbb), rotation) + charo + position
if !isfinite_rect(bb)
bb = charbb
Expand Down
32 changes: 15 additions & 17 deletions src/layouting/layouting.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,14 +79,13 @@ function glyph_collection(

# collect information about every character in the string
charinfos = broadcast((c for c in str), font_per_char, fontscale_px) do char, font, scale
unscaled_extent = get_extent(font, char)
lineheight = Float32(font.height / font.units_per_EM * lineheight_factor * scale)
unscaled_hi_bb = height_insensitive_boundingbox(unscaled_extent, font)
hi_bb = Rect2f(
Makie.origin(unscaled_hi_bb) * scale,
widths(unscaled_hi_bb) * scale)
(char = char, font = font, scale = scale, hadvance = hadvance(unscaled_extent) * scale,
hi_bb = hi_bb, lineheight = lineheight, extent = unscaled_extent)
(
char = char,
font = font,
scale = scale,
lineheight = Float32(font.height / font.units_per_EM * lineheight_factor * scale),
extent = GlyphExtent(font, char)
)
end

# split the character info vector into lines after every \n
Expand All @@ -112,7 +111,7 @@ function glyph_collection(

for (i, ci) in enumerate(charinfos)
push!(xs[end], x)
x += charinfos[i].hadvance
x += ci.extent.hadvance * ci.scale

if 0 < word_wrap_width < x && (ci.char == ' ' || i == length(charinfos)) &&
last_space_local_idx != 0
Expand All @@ -122,13 +121,13 @@ function glyph_collection(
xs[end-1] = xs[end-1][1:last_space_local_idx]
push!(lineinfos, view(charinfos, last_line_start:last_space_global_idx))
last_line_start = last_space_global_idx+1
x = xs[end][end] + charinfos[i].hadvance
x = xs[end][end] + ci.extent.hadvance * ci.scale

# TODO Do we need to redo the metrics for newlines?
charinfos[last_space_global_idx] = let
_, font, scale, hadvance, hi_bb, lineheight, extent = charinfos[last_space_global_idx]
(char = '\n', font = font, scale = scale, hadvance = hadvance,
hi_bb = hi_bb, lineheight = lineheight, extent = extent)
_, font, scale, lineheight, extent = charinfos[last_space_global_idx]
(char = '\n', font = font, scale = scale,
lineheight = lineheight, extent = extent)
end

if i == length(charinfos)
Expand Down Expand Up @@ -158,7 +157,7 @@ function glyph_collection(
# if the last and not the only character is \n, take the previous one
# to compute the width
i = (nchars > 1 && line[end].char == '\n') ? nchars - 1 : nchars
xx[i] + line[i].hadvance
xx[i] + line[i].extent.hadvance * line[i].scale
end

# the maximum width is needed for justification
Expand Down Expand Up @@ -219,11 +218,11 @@ function glyph_collection(
# for y alignment, we need the largest ascender of the first line
# and the largest descender of the last line
first_line_ascender = maximum(lineinfos[1]) do l
ascender(l.font) * l.scale
l.scale * l.extent.ascender
end

last_line_descender = minimum(lineinfos[end]) do l
descender(l.font) * l.scale
l.scale * l.extent.descender
end

# compute the height of all lines together
Expand All @@ -244,7 +243,6 @@ function glyph_collection(
else
error("Invalid valign $valign. Valid values are <:Number, :bottom, :baseline, :top, and :center.")
end

ys .- first_line_ascender .+ (1 - va) .* overall_height
end

Expand Down
6 changes: 3 additions & 3 deletions src/makielayout/blocks/textbox.jl
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ function initialize_block!(tbox::Textbox)

hadvances = Float32[]
broadcast_foreach(glyphcollection.extents, glyphcollection.scales) do ex, sc
hadvance = Makie.FreeTypeAbstraction.hadvance(ex) * sc[1]
hadvance = ex.hadvance * sc[1]
push!(hadvances, hadvance)
end

Expand Down Expand Up @@ -257,8 +257,8 @@ function charbbs(text)
end
pos = Point2f(text.position[])
bbs = Rect2f[]
broadcast_foreach(gc.extents, gc.scales, gc.origins, gc.fonts) do ext, sc, ori, font
bb = Makie.FreeTypeAbstraction.height_insensitive_boundingbox(ext, font) * sc
broadcast_foreach(gc.extents, gc.scales, gc.origins) do ext, sc, ori
bb = Makie.height_insensitive_boundingbox_with_advance(ext) * sc
fr = Rect2f(Point2f(ori) + bb.origin + pos, bb.widths)
push!(bbs, fr)
end
Expand Down
2 changes: 1 addition & 1 deletion src/makielayout/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ end
"The padding between the xlabel and the ticks or axis."
xlabelpadding::Float64 = 3f0
"The padding between the ylabel and the ticks or axis."
ylabelpadding::Float64 = 5f0 # because of boundingbox inaccuracies of ticklabels
ylabelpadding::Float64 = 5f0 # xlabels usually have some more visual padding because of ascenders, which are larger than the hadvance gaps of ylabels
"The font family of the xticklabels."
xticklabelfont::Makie.FreeTypeAbstraction.FTFont = @inherit(:font, "TeX Gyre Heros Makie")
"The font family of the yticklabels."
Expand Down
36 changes: 35 additions & 1 deletion src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,40 @@ function collect_vector(sv::ScalarOrVector, n::Int)
end
end

"""
GlyphExtent

Store information about the bounding box of a single glyph.
"""
struct GlyphExtent
ink_bounding_box::Rect2f
ascender::Float32
descender::Float32
hadvance::Float32
end

function GlyphExtent(font, char)
extent = get_extent(font, char)
ink_bb = FreeTypeAbstraction.inkboundingbox(extent)
ascender = FreeTypeAbstraction.ascender(font)
descender = FreeTypeAbstraction.descender(font)
hadvance = FreeTypeAbstraction.hadvance(extent)

return GlyphExtent(ink_bb, ascender, descender, hadvance)
end

function GlyphExtent(texchar::TeXChar)
l = MathTeXEngine.leftinkbound(texchar)
r = MathTeXEngine.rightinkbound(texchar)
b = MathTeXEngine.bottominkbound(texchar)
t = MathTeXEngine.topinkbound(texchar)
ascender = MathTeXEngine.ascender(texchar)
descender = MathTeXEngine.descender(texchar)
hadvance = MathTeXEngine.hadvance(texchar)

return GlyphExtent(Rect2f((l, b), (r - l, t - b)), ascender, descender, hadvance)
end

"""
GlyphCollection

Expand All @@ -314,7 +348,7 @@ struct GlyphCollection
glyphs::Vector{Char}
fonts::Vector{FTFont}
origins::Vector{Point3f}
extents::Vector{FreeTypeAbstraction.FontExtent{Float32}}
extents::Vector{GlyphExtent}
scales::ScalarOrVector{Vec2f}
rotations::ScalarOrVector{Quaternionf}
colors::ScalarOrVector{RGBAf}
Expand Down
8 changes: 7 additions & 1 deletion test/text.jl
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,19 @@
@test glyph_collection.glyphs == chars
@test glyph_collection.fonts == [font for _ in 1:4]
@test all(isapprox.(glyph_collection.origins, [Point3f(x, 0, 0) for x in origins], atol = 1e-10))
@test glyph_collection.extents == unit_extents
@test glyph_collection.scales.sv == [Vec2f(p.textsize[]) for _ in 1:4]
@test glyph_collection.rotations.sv == [Quaternionf(0,0,0,1) for _ in 1:4]
@test glyph_collection.colors.sv == [RGBAf(0,0,0,1) for _ in 1:4]
@test glyph_collection.strokecolors.sv == [RGBAf(0,0,0,0) for _ in 1:4]
@test glyph_collection.strokewidths.sv == Float32[0, 0, 0, 0]

makie_hi_bb = Makie.height_insensitive_boundingbox.(glyph_collection.extents)
makie_hi_bb_wa = Makie.height_insensitive_boundingbox_with_advance.(glyph_collection.extents)
fta_hi_bb = FreeTypeAbstraction.height_insensitive_boundingbox.(unit_extents, Ref(font))
fta_ha = FreeTypeAbstraction.hadvance.(unit_extents)
@test makie_hi_bb == fta_hi_bb
@test fta_ha == [bb.origin[1] + bb.widths[1] for bb in makie_hi_bb_wa]

# Test quad data
positions, char_offsets, quad_offsets, uvs, scales = Makie.text_quads(
to_ndim(Point3f, p.position[], 0), glyph_collection,
Expand Down