Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

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

Setting vertical marks #318

Closed
alerque opened this issue May 14, 2016 · 6 comments
Closed

Setting vertical marks #318

alerque opened this issue May 14, 2016 · 6 comments
Labels
question Ask for advice or investigate solutions

Comments

@alerque
Copy link
Member

alerque commented May 14, 2016

How should something like this be typeset:

selection_215

This layout is correct (and generated by SILE) but the code for it is too brittle to put in an automatic template. I can massage it given specific content, but with the content being an unknown I'm having a hard time coming up with a template.

Currently I'm dropping the image with a fixed height, then skipping back negative a little more than that height, then adding lskip, then typesetting the 5 lines of data, then turning off the lskip and going back to normal.

SILE.registerCommand("qrimg", function(options, content)
    SU.debug("viachristus", SILE.typesetter.frame.state.cursorY)
    SILE.call("skip", { height="6.5em" })
    SU.debug("viachristus", SILE.typesetter.frame.state.cursorY)
    SILE.call("img", { src=qrimg, height="5.8em" })
    SILE.call("skip", { height="-6.3em" })
    SILE.call("set", { parameter="document.lskip",value="5em" })
end)

qrimg = "./mujdenin_gucu-url.png"
\define[command=meta:identifiers]{
\font[weight=600,style=Bold]{ISBN}: 978-605-66445-1-1\break
\font[weight=600,style=Bold]{E-kitap}: 978-605-66445-0-4\break
\font[weight=600,style=Bold]{Sertifika No}: 16231\break
\font[weight=600,style=Bold]{Sürüm:} \meta:surum\break
\font[weight=600,style=Bold]{URL:} \meta:url\break
}
\define[command=meta:url]{https://yayinlar.viachristus.com/mujdenin_gucu}
\define[command=meta:surum]{mujdenin_gucu@isbn-basvuru-22-g068e74f*}

\qrimg{}
\meta:identifiers{}

\set[parameter=document.lskip]

The trouble is I don't actually know ahead of time how much content there will be. For some instances there might only be three lines of content. Given my current code this would cause the next block to be typeset overlapping the barcode.

I tried using SILE.typesetter.frame.state.cursorY, but this value does not get updated in between elements like I would need it to be to do math and figure out how much I moved relative to where the image was output. It updates if I call SILE.typesetter:chuck(), but of course that screws up the page layout, notably the \vfill at the top of the page that puts this whole thing at the bottom of the page gets eaten.

The nearest thing I found in the docs was the "sidenotes" example using the cursor position, but like I said this doesn't seem to update when I need it to.

What's the best tool for the job here?

@alerque alerque added the question Ask for advice or investigate solutions label May 14, 2016
@simoncozens
Copy link
Member

Off the top of my head, I would try putting the text into a vbox; have a look at the simple table package. (Yeah, doing layout with tables feels as bad here as it does in HTML, but it's worth a look.) Or you could try doing what \float does - split into two frames, then join again later. I will try and have a fiddle myself, but that may get you started.

@alerque alerque modified the milestone: v0.9.6 Aug 12, 2016
@alerque
Copy link
Member Author

alerque commented Nov 1, 2016

I've tried a couple stabs at this and fallen pretty flat every time. My current hack is to look through the paragraph and count the number of penalties. If it's less than 5 I stuff a couple more in. This works for this particular use but it probably doesn't generalize very well making this a hard problem for users to solve:

        if publisher then
          SILE.call("skip", { height = "5.4em" })
          SILE.settings.temporarily(function ()
            SILE.call("img", { src = qrimg, height = "5.8em" })
            SILE.call("skip", { height = "-6.3em" })
            SILE.settings.set("document.lskip", SILE.nodefactory.newGlue({ width = imgUnit * 6.5 }))
            if SILE.Commands["meta:identifiers"] then SILE.call("meta:identifiers") end
            SILE.call("font", { weight = 600, style = "Bold" }, { "Sürüm: " })
            SILE.call("font", { family = "Hack", size = "0.8em" }, SILE.Commands["meta:surum"])
            SILE.call("break")
            SILE.call("font", { weight = 600, style = "Bold" }, { "URL: " })
            SILE.call("font", { family = "Hack", size = "0.8em" }, SILE.Commands["meta:url"])
            -- Hack around not being able to output a vbox with an indent
            -- See https://github.com/simoncozens/sile/issues/318
            local lines = 1
            for i = 1, #SILE.typesetter.state.nodes do
              lines = lines + (SILE.typesetter.state.nodes[i]:isPenalty() and 1 or 0)
            end
            for i = lines, 5 do
              SILE.call("hbox")
              SILE.call("break")
            end
            SILE.call("par")
          end)
        end

The key here is that I don't know how many lines meta:identifiers will output. It could be 0–3 leaving me needing to output 3-n blank lines to get past the reserved space. There must be a more elegant way to do this.

@alerque alerque modified the milestones: v0.9.6, v0.9.7 Jan 11, 2019
@alerque alerque modified the milestones: v0.11.2, v0.11.x Sep 16, 2021
@alerque alerque modified the milestones: v0.12.1, v0.12.x Jan 12, 2022
@alerque alerque modified the milestones: v0.12.3, v0.12.x Mar 2, 2022
@alerque alerque modified the milestones: v0.12.x, v0.13.x Apr 18, 2022
@alerque alerque modified the milestones: v0.13.x, v0.14.x Jun 24, 2022
@Omikhleia
Copy link
Member

There would be so many ways to achieve this, with probably variants depending on how one wants to handle all the decisions left undefined in the initial question (e.g. maximum width of the text content, maximum height of the image, edge cases when these get incompatible with each other vs. the available page width, etc. -- and, why not, even min-max both blocks).

Considering the simplest case, though... Let me give it a try, to back my old claim elsewhere it was all doable with the appropriate tools...

image

LGTM 😺

Here are the steps:

luarocks install --server=https://luarocks.org/dev ptable.sile
sile imageatparside.sil

Where imageatparside.sil is:

\begin[papersize=a5,class=plain]{document}
\neverindent
\use[module=packages.parbox]
\use[module=packages.image]
\font[family=Libertinus Serif,size=12]

\lua{
SILE.registerCommand("textWithImageOnSide", function (options, content)
  SILE.call("medskip")
  -- Box the paragraphs, with max size = 75%lw or whathever we want
  SILE.call("parbox", { width="75%lw", minimize=true, valign="bottom" }, content)
  -- Steal it back...
  local hbox = table.remove(SILE.typesetter.state.nodes)
  -- Measure height
  local H = hbox.height
  -- Box the image scaled to that height
  local imbox = SILE.call("hbox", {}, function ()
    SILE.call("img", { src = options.src, height = H })
  end)
  -- Some horizontal spacing
  SILE.call("kern", { width = "1spc" })
  --- And then push the paragraph box back
  SILE.typesetter:pushHbox(hbox)
  SILE.call("medskip")
end)
}

\begin[src=sherlock.png]{textWithImageOnSide}
Lorem\par
Ipsum\par
Dolor sit amet
\end{textWithImageOnSide}

\begin[src=sherlock.png]{textWithImageOnSide}
Lorem\par
Ipsum\par
Dolor sit amet\par
More dolor\par
Ipsum ipsums
\end{textWithImageOnSide}

\end{document}

Does it answer the question?

@Omikhleia
Copy link
Member

The suggested answer currently only works well with the boxed paragraph doesn't contain migrating contents (footnotes). "Stealing" content from the typesetter queue is bad otherwise.

As an aside addition, indirectly related to the original example: instead of an image for the QR code, one may be interested in giving a try to qrcode.sile :)

@Omikhleia
Copy link
Member

A new version (with the latest "parbox.sile" module at this date), better for two reasons at least:

  • Avoids the box stealing trick
  • Properly handles footnotes
\begin[papersize=a6,class=book]{document}
\neverindent
\nofolios
\use[module=packages.parbox]
\use[module=packages.image]
\font[family=Libertinus Serif,size=12]

\lua{
-- DOH, we cannot use SILE.registerCommand here without deprecation warning
-- so we have to retrieve the class instance with this long-winded way
local class = SILE.documentState.documentClass 

-- DOH "\use" above doesn't seem to load the package into the class:
-- local pboxer = class.packages.parbox -- NOPE!
local pboxer = SILE.require("packages.parbox") -- ERM, works, but double-loaded in a way?
-- OR (long-winded too):
-- class:loadPackage("parbox") -- ERM, works, but double-loaded in a way?
-- local pboxer = class.packages.parbox -- Aye, it's here now!

class:registerCommand("textWithImageOnSide", function (options, content)
  SILE.call("medskip")
  -- Box the paragraphs, with max size = 75%lw or whathever we want
  local hbox, hlist = pboxer:makeParbox({ width="75%lw", minimize=true, valign="bottom" }, content)
  -- Measure height
  local H = hbox.height
  -- Box the image scaled to that height
  local imbox = SILE.call("hbox", {}, function ()
    SILE.call("img", { src = options.src, height = H })
  end)
  -- Some horizontal spacing
  SILE.call("kern", { width = "1spc" })
  -- And then push the paragraph box back...
  SILE.typesetter:pushHbox(hbox)
  -- ... As well as any migrating content from within it, just after.
  for _, h in ipairs(hlist) do
    SILE.typesetter:pushHorizontal(h)
  end
  SILE.call("medskip")
end)
}

\begin[src=sherlock.png]{textWithImageOnSide}
Lorem\footnote{This is a footnote}\par
Ipsum\par
Dolor sit amet
\end{textWithImageOnSide}

\begin[src=sherlock.png]{textWithImageOnSide}
Lorem\par
Ipsum\par
Dolor sit amet\par
More dolor\par
Ipsum ipsums
\end{textWithImageOnSide}

\end{document}

Comments welcome, especially on how to properly handle the "DOH" commented sections in such examples. (It works, but is rather long-winded... Of course, moving the Lua bit in some package or dedicated class would avoid it all.)

@alerque
Copy link
Member Author

alerque commented Feb 15, 2023

Fixing #1510 should address most of this. The deprecation warnings thrown in this context are bogus because the context for their registration is known. I was trying to get unscoped registrations out out of packages, not out of documents! As an alternative you can use a \lua{} block (or more logically a \use{} block to return a module that is basically a lambda package. I'll try to drop an example soon because that needs documenting.

@sile-typesetter sile-typesetter locked and limited conversation to collaborators Mar 26, 2023
@Omikhleia Omikhleia converted this issue into discussion #1741 Mar 26, 2023
@alerque alerque removed this from the v0.x.y milestone Oct 11, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Labels
question Ask for advice or investigate solutions
Projects
None yet
Development

No branches or pull requests

3 participants