forked from MakieOrg/Makie.jl
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Refactor display code to be Screen centric (MakieOrg#2306)
* Only rasterize if the backend is not itself raster * Define width of CairoScreen * Make colorbuffer use the size of the screen, not the scene This allows arbitrary scaling in CairoMakie, remains constant in GLMakie, and probably breaks WGLMakie. * Add GeometryBasics.widths for ThreeDisplay * Add GeometryBasics.widths for WebDisplay * Fix inadvertent bug * Add news entry * Decrease the number of evaljs_value calls * broadcast in WGLMakie method * Pass kwargs along to backend_show in backend_display for CairoMakie * Pass arbitrary kwargs along * convert Iterators.Pairs to namedtuple in backend_display for CairoMakie * Splat kwargs as a vector of pairs * refactor display code * new screen constructors * get CairoMakie & GLMakie to work * fix tests * more context switching * try thiss * hm * make sure we track context in shader compilation * clean up ROBJ and context switching * fix RPRMakie * fix thy backends * fix stepper and docs * remove all inline! use * fix GLMakie screen deregistering * fix offset in Stepper for CairoMakie * fix benchmarks + precompiles * implement switching of mimes * move display config to theme * fix parse error * bring back precompiles * small fixes/improvements * incorperate changes from MakieOrg#2231 and refactor scene Co-authored-by: Robert Bennett <[email protected]> * fix CI ? * improved screen clean up * clean up and tests * add logging * fix makie unit tests * let CI fail gracefully * fix import * remove last GLMakie.Screen related globals * small improvements for Pluto + friends * add comment * clean up docs * move preferred mime machinery to CairoMakie, since its not needed anywhere else * remove set_preferred_mime! from tests etc * fix mime test * last clean up & address review * update docs * initialize array * deprecate set_window_config! properly * forgot another constructor * small clean up and doc fixes * small doc fixes Co-authored-by: Anshul Singhvi <[email protected]> Co-authored-by: Anshul Singhvi <[email protected]> Co-authored-by: Robert Bennett <[email protected]>
- Loading branch information
Showing
127 changed files
with
2,483 additions
and
1,785 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
# TODO, move those to Cairo? | ||
|
||
function set_font_matrix(ctx, matrix) | ||
ccall((:cairo_set_font_matrix, Cairo.libcairo), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}), ctx.ptr, Ref(matrix)) | ||
end | ||
|
||
function get_font_matrix(ctx) | ||
matrix = Cairo.CairoMatrix() | ||
ccall((:cairo_get_font_matrix, Cairo.libcairo), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}), ctx.ptr, Ref(matrix)) | ||
return matrix | ||
end | ||
|
||
function cairo_font_face_destroy(font_face) | ||
ccall( | ||
(:cairo_font_face_destroy, Cairo.libcairo), | ||
Cvoid, (Ptr{Cvoid},), | ||
font_face | ||
) | ||
end | ||
|
||
function set_ft_font(ctx, font) | ||
|
||
font_face = ccall( | ||
(:cairo_ft_font_face_create_for_ft_face, Cairo.libcairo), | ||
Ptr{Cvoid}, (Makie.FreeTypeAbstraction.FT_Face, Cint), | ||
font, 0 | ||
) | ||
|
||
ccall((:cairo_set_font_face, Cairo.libcairo), Cvoid, (Ptr{Cvoid}, Ptr{Cvoid}), ctx.ptr, font_face) | ||
|
||
return font_face | ||
end | ||
|
||
struct CairoGlyph | ||
index::Culong | ||
x::Cdouble | ||
y::Cdouble | ||
end | ||
|
||
function show_glyph(ctx, glyph, x, y) | ||
cg = Ref(CairoGlyph(glyph, x, y)) | ||
ccall((:cairo_show_glyphs, Cairo.libcairo), | ||
Nothing, (Ptr{Nothing}, Ptr{CairoGlyph}, Cint), | ||
ctx.ptr, cg, 1) | ||
end | ||
|
||
function glyph_path(ctx, glyph::Culong, x, y) | ||
cg = Ref(CairoGlyph(glyph, x, y)) | ||
ccall((:cairo_glyph_path, Cairo.libcairo), | ||
Nothing, (Ptr{Nothing}, Ptr{CairoGlyph}, Cint), | ||
ctx.ptr, cg, 1) | ||
end | ||
|
||
function surface_set_device_scale(surf, device_x_scale, device_y_scale=device_x_scale) | ||
# this sets a scaling factor on the lowest level that is "hidden" so its even | ||
# enabled when the drawing space is reset for strokes | ||
# that means it can be used to increase or decrease the image resolution | ||
ccall( | ||
(:cairo_surface_set_device_scale, Cairo.libcairo), | ||
Cvoid, (Ptr{Nothing}, Cdouble, Cdouble), | ||
surf.ptr, device_x_scale, device_y_scale) | ||
end | ||
|
||
function set_miter_limit(ctx, limit) | ||
ccall((:cairo_set_miter_limit, Cairo.libcairo), Cvoid, (Ptr{Nothing}, Cdouble), ctx.ptr, limit) | ||
end | ||
|
||
function get_render_type(surface::Cairo.CairoSurface) | ||
typ = ccall((:cairo_surface_get_type, Cairo.libcairo), Cint, (Ptr{Nothing},), surface.ptr) | ||
typ == Cairo.CAIRO_SURFACE_TYPE_PDF && return PDF | ||
typ == Cairo.CAIRO_SURFACE_TYPE_PS && return EPS | ||
typ == Cairo.CAIRO_SURFACE_TYPE_SVG && return SVG | ||
typ == Cairo.CAIRO_SURFACE_TYPE_IMAGE && return IMAGE | ||
error("Unsupported surface type: $(typ)") | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
|
||
######################################### | ||
# Backend interface to Makie # | ||
######################################### | ||
|
||
""" | ||
tryrun(cmd::Cmd) | ||
Try to run a command. Return `true` if `cmd` runs and is successful (exits with a code of `0`). | ||
Return `false` otherwise. | ||
""" | ||
function tryrun(cmd::Cmd) | ||
try | ||
return success(cmd) | ||
catch e | ||
return false | ||
end | ||
end | ||
|
||
function openurl(url::String) | ||
if Sys.isapple() | ||
tryrun(`open $url`) && return | ||
elseif Sys.iswindows() | ||
tryrun(`powershell.exe start $url`) && return | ||
elseif Sys.isunix() | ||
tryrun(`xdg-open $url`) && return | ||
tryrun(`gnome-open $url`) && return | ||
end | ||
tryrun(`python -mwebbrowser $(url)`) && return | ||
# our last hope | ||
tryrun(`python3 -mwebbrowser $(url)`) && return | ||
@warn("Can't find a way to open a browser, open $(url) manually!") | ||
end | ||
|
||
function display_path(type::String) | ||
if !(type in ("svg", "png", "pdf", "eps")) | ||
error("Only \"svg\", \"png\", \"eps\" and \"pdf\" are allowed for `type`. Found: $(type)") | ||
end | ||
return abspath(joinpath(@__DIR__, "display." * type)) | ||
end | ||
|
||
function Base.display(screen::Screen{IMAGE}, scene::Scene; connect=false) | ||
path = display_path("png") | ||
cairo_draw(screen, scene) | ||
Cairo.write_to_png(screen.surface, path) | ||
if screen.visible | ||
openurl("file:///" * path) | ||
end | ||
end | ||
|
||
function Makie.backend_show(screen::Screen{SVG}, io::IO, ::MIME"image/svg+xml", scene::Scene) | ||
|
||
cairo_draw(screen, scene) | ||
Cairo.flush(screen.surface) | ||
Cairo.finish(screen.surface) | ||
|
||
svg = String(take!(Makie.raw_io(screen.surface.stream))) | ||
|
||
# for some reason, in the svg, surfaceXXX ids keep counting up, | ||
# even with the very same figure drawn again and again | ||
# so we need to reset them to counting up from 1 | ||
# so that the same figure results in the same svg and in the same salt | ||
surfaceids = sort(unique(collect(m.match for m in eachmatch(r"surface\d+", svg)))) | ||
|
||
for (i, id) in enumerate(surfaceids) | ||
svg = replace(svg, id => "surface$i") | ||
end | ||
|
||
# salt svg ids with the first 8 characters of the base64 encoded | ||
# sha512 hash to avoid collisions across svgs when embedding them on | ||
# websites. the hash and therefore the salt will always be the same for the same file | ||
# so the output is deterministic | ||
salt = String(Base64.base64encode(SHA.sha512(svg)))[1:8] | ||
|
||
ids = sort(unique(collect(m[1] for m in eachmatch(r"id\s*=\s*\"([^\"]*)\"", svg)))) | ||
|
||
for id in ids | ||
svg = replace(svg, id => "$id-$salt") | ||
end | ||
|
||
print(io, svg) | ||
return screen | ||
end | ||
|
||
function Makie.backend_show(screen::Screen{PDF}, io::IO, ::MIME"application/pdf", scene::Scene) | ||
cairo_draw(screen, scene) | ||
Cairo.finish(screen.surface) | ||
return screen | ||
end | ||
|
||
function Makie.backend_show(screen::Screen{EPS}, io::IO, ::MIME"application/postscript", scene::Scene) | ||
cairo_draw(screen, scene) | ||
Cairo.finish(screen.surface) | ||
return screen | ||
end | ||
|
||
function Makie.backend_show(screen::Screen{IMAGE}, io::IO, ::MIME"image/png", scene::Scene) | ||
cairo_draw(screen, scene) | ||
Cairo.write_to_png(screen.surface, io) | ||
return screen | ||
end | ||
|
||
# Disabling mimes and showable | ||
|
||
const DISABLED_MIMES = Set{String}() | ||
const SUPPORTED_MIMES = Set([ | ||
"image/svg+xml", | ||
"application/pdf", | ||
"application/postscript", | ||
"image/png" | ||
]) | ||
|
||
function Makie.backend_showable(::Type{Screen}, ::MIME{SYM}) where SYM | ||
supported_mimes = Base.setdiff(SUPPORTED_MIMES, DISABLED_MIMES) | ||
return string(SYM) in supported_mimes | ||
end | ||
|
||
""" | ||
to_mime_string(mime::Union{String, Symbol, MIME}) | ||
Converts anything like `"png", :png, "image/png", MIME"image/png"()` to `"image/png"`. | ||
""" | ||
function to_mime_string(mime::Union{String, Symbol, MIME}) | ||
if mime isa MIME | ||
mime_str = string(mime) | ||
if !(mime_str in SUPPORTED_MIMES) | ||
error("Mime $(mime) not supported by CairoMakie") | ||
end | ||
return mime_str | ||
else | ||
mime_str = string(mime) | ||
if !(mime_str in SUPPORTED_MIMES) | ||
mime_str = string(to_mime(convert(RenderType, mime_str))) | ||
end | ||
return mime_str | ||
end | ||
end | ||
|
||
""" | ||
disable_mime!(mime::Union{String, Symbol, MIME}...) | ||
The default is automatic, which lets the display system figure out the best mime. | ||
If set to any other valid mime, will result in `showable(any_other_mime, figurelike)` to return false and only return true for `showable(preferred_mime, figurelike)`. | ||
Depending on the display system used, this may result in nothing getting displayed. | ||
""" | ||
function disable_mime!(mimes::Union{String, Symbol, MIME}...) | ||
empty!(DISABLED_MIMES) # always start from 0 | ||
if isempty(mimes) | ||
# Reset disabled mimes when called with no arguments | ||
return | ||
end | ||
mime_strings = Set{String}() | ||
for mime in mimes | ||
push!(mime_strings, to_mime_string(mime)) | ||
end | ||
union!(DISABLED_MIMES, mime_strings) | ||
return | ||
end | ||
|
||
function enable_only_mime!(mimes::Union{String, Symbol, MIME}...) | ||
empty!(DISABLED_MIMES) # always start from 0 | ||
if isempty(mimes) | ||
# Reset disabled mimes when called with no arguments | ||
return | ||
end | ||
mime_strings = Set{String}() | ||
for mime in mimes | ||
push!(mime_strings, to_mime_string(mime)) | ||
end | ||
union!(DISABLED_MIMES, setdiff(SUPPORTED_MIMES, mime_strings)) | ||
return | ||
end |
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.