개념 증명

개념 증명

출력 PDF에서 하이픈을 사용할 수 없는 단어를 자동으로 강조 표시할 수 있는 패키지가 있습니까? 즉, 하이픈 넣기 단어 목록에 없는 단어입니다. 예를 들어:

여기에 이미지 설명을 입력하세요

저는 폴리글로시아 패키지를 사용하고 있습니다. 매우 감사합니다!

답변1

개념 증명

우리는 다음과 같은 몇 가지 일반적인 패키지를 확인했습니다.울렘(도널드 아르세노) 그리고영혼(Melchior Franz) 그 후 우리는 다음으로 관심을 옮겼습니다.쇼하이픈,루아-체크-하이픈그리고루아-시각-디버그Patrick Gundlach가 만든 패키지. 불행하게도 OP에는 이러한 패키지가 제공하는 것과 반대되는 것이 필요합니다.

우리는 다음을 분석하고 배우는 것으로 작업을 시작했습니다.TeX.SX의 이 코드(또한보십시오http://wiki.luatex.org/index.php/Show_the_hyphenation_points) Patrick Gundlach의 글입니다. 우리는 항상 지원을 받고 있습니다.LuaTeX 참조 매뉴얼,여기서는 정의된 노드 유형을 확인했습니다(매뉴얼의 8장 노드, 첫 번째 페이지, 169페이지 이상 참조). 다음 페이지에서 해당 분야에 대해 읽을 수 있습니다.

특히 다음 유형이 필요했습니다.

  • hlist (0), 수평 목록,
  • vlist (1), 수직 목록,
  • 디스크 (7), 단어에 하이픈을 넣을 수 있는 곳,
  • whasit(8), 새 노드 생성에 적합한 유형,
  • 접착제(10), 공백,
  • 커닝(11), 커닝, 및
  • 이런 종류의 작업에 대한 핵심 노드 유형인 glyph (37).

우리의 임무는 모든 노드를 살펴보고, 해당 ID를 Lua 테이블에 수집 및 저장하고, 텍스트 수준에서 몇 가지 기본 분석을 수행한 후 결과에 대한 기본 강조 표시를 수행하는 것이었습니다(이 예에서는 모든 문자에 밑줄을 사용했습니다).

해당 단어를 강조 표시해야 하는 최소 문자 수를 전달하고 있습니다. 단일 단어는 문자, 숫자, 구두점 등으로 구성됩니다. 우리는 이것이 개념 증명에 충분하다고 믿습니다.

하이픈을 표시하는 원래 코드는 재귀 알고리즘을 사용하여 노드 트리를 통과합니다. 두 개의 패스가 필요했기 때문에 해당 함수( show_hyph)를 다른 함수( )로 래핑했습니다 towork. 분석은 showme함수에서 수행됩니다. 우리는 사용자 데이터를 사용하고 head, 함수를 사용하여 필드를 인쇄할 수 있습니다 getmetatable. 이는 노드에 대한 추가 정보를 인쇄할 뿐만 아니라 코드에서 주석 처리됩니다.

텍스트 분석은 주로 다음과 같은 여러 조건으로 구성됩니다.

  • ID 0 또는 ID 10 다음에 ID 37이 옵니다(단어에 이미 하이픈을 넣을 수 없음). 이는 단어의 시작입니다. 새로운 줄이나 공백 뒤에 문자 모양이 오는 것입니다.
  • ID 7은 디스크가 있을 수 있다는 의미이며 해당 단어는 우리에게 관심이 없습니다.
  • ID 11(커닝) 또는 ID 37(글리프)은 단어의 일부이므로 추가 분석을 위해 해당 부분을 포함합니다.
  • ID 37 다음에 ID 10이 오면 단어가 끝납니다.

우리는 모든 정보를 Lua 테이블에 저장합니다. 우리가 사용한 단어를 표시하기 위해 malsizetrue(글리프+커닝 노드), 우리가 사용한 사용자와의 상호 작용을 위해 malsize(글리프만) 단어 길이에 대한 두 개의 변수가 필요했습니다 . 처음에는 이런 용어로 단어를 생각하는 것이 낯설었지만 꼭 필요한 일이었습니다.

head.width적절한 밑줄을 표시하기 위해 ( 단위)를 사용했습니다 sp. 아래 예에서는 모든 문자에 개별적으로 밑줄이 그어져 있으므로 단어당 한 줄씩 그리도록 개선할 수 있습니다. 우리는 이 아이디어를 코드에 대한 추가 실험을 위해 열어두었습니다. 그러려면 함수의 첫 번째 실행에서 너비를 저장하고 Lua 수준의 두 번째 실행에서 이를 사용해야 합니다.

다음 예에서는 몇 가지 기본 텍스트를 사용했으며 단어당 최소 문자 수를 1에서 8까지 설정했습니다. 코드와 결과 미리 보기(8페이지)를 동봉합니다. 이 예에서는 예상대로 작동하지만 이 코드 조각에는 더 많은 테스트가 필요한 것 같습니다.

우리는 달린다 lualatex mal-hyph.tex.

% lualatex mal-hyph.tex
\documentclass[a4paper]{article}
\pagestyle{empty}
\usepackage{luacode} % the core package in LuaLaTeX, recommended is luatextra
\usepackage[english]{babel} % loading some hyphenation rules
\usepackage{kantlipsum} % loading some text
\usepackage{fontspec} % loading some font

\begin{luacode*}
-- This is the core function for callback...
function towork(head)

-- This inner function is recursive...
function show_hyph(head)
while head do

  -- If we want to see userdata of >head<...
  -- for i,j in pairs(getmetatable(head)) do
  --    print(i,j)
  -- end

  -- If we need to get nodes ID..., this is the way.
  --[=[  io.write(head.id.." ")
    if head.id ==10 then io.write(" ") end
    if head.id == 37 then 
       io.write(unicode.utf8.char(head.char).."; ")
       end    
    --]=] -- be silent

    if head.id == 0 or head.id == 1 then
       show_hyph(head.head) -- the core of recursion
    end -- if, head.id, 0 (hlist) or 1 (vlist)

    counter=counter+1 -- number of nodes
    malglyphs[counter]=head.id -- saving IDs for later analysis

if run then -- We can add nodes after analysis...
  if maldraw[counter]==1 then -- These letters belong to unhyphenateable words.
      local n = node.new("whatsit","pdf_literal") -- Underline them, please,
      n.mode = 0
      if head.width then dista=head.width/65535 else dista=0 end -- with proper  width,
      distb=0
      n.data = "q 1 w 0 0 1 RG "..-dista.." -2 m "..distb.." -2 l S Q" -- with some common line.
      n.next = head.next -- Add line to the node tree.
      n.prev = head
      head.next = n
      head = n
  end -- if we are done with lines.

    if head.id == 7 and run then -- a divis, this is an original example, addition of disc
      local n = node.new("whatsit","pdf_literal")
      n.mode = 0
      n.data = "q 0.9 w 1 .1 .1 RG 0 2 m 0 7 l S Q" -- an original setting was: q 0.3 w 0 2 m 0 7 l S Q
      n.next = head.next
      n.prev = head
      head.next = n
      head = n
    end -- if, head.id==7
end -- if, run

head = head.next -- go to the next node
end -- while, node three

end -- function, show_hyph


-- This function analyses ID of nodes.
function showme()
-- Initialize some variables.
malwrite=0 -- Can I store a unhyphenateable word?
maldraw={} -- Table with 1s for storing information.
malsize=0 -- A size of the last word (only letters, ID 37).
malsizetrue=0 -- A size of the last word (letters+kerning, IDs 11+37).
broken=0 -- Is a word already hyphenated?

for malcounter=1,#malglyphs do -- Let's analyse all nodes.

-- Print some letters from actual position backward.
-- print(malglyphs[malcounter-2], malglyphs[malcounter-1], malglyphs[malcounter]) 

-- Are we at the beginning of the word?
if  (malglyphs[malcounter-1]==0 or malglyphs[malcounter-1]==10) and malglyphs[malcounter]==37 and broken~=1 then malwrite=1; malsize=0; malsizetrue=0 end

-- Are we at the end of the word? Can we modify data in our Lua table?
if malglyphs[malcounter-1]==37 and (malglyphs[malcounter]==10 or malglyphs[malcounter]==12) then 
   if malwrite==1 and malsize>=malmax then -- used to be: malsize>0
   for malback=1,malsizetrue do -- set letters of unhyphenated word for underlining/highlighting, plus kerning
      maldraw[malcounter-malback]=1 -- mark them letter by letter
   end -- for, malback
   end -- if, malwrite
end -- if, malglyphs...

-- Are we in the middle of the hyphenated word?
if malglyphs[malcounter]==7 then broken=1 end -- Yes, we are!
if malglyphs[malcounter]==37 then broken=0 end -- No, at least not at the beginning of the line!

-- Is this a node with letter or kerning in some word?
if malglyphs[malcounter]==37 or malglyphs[malcounter]==11 then 
   malsizetrue=malsizetrue+1 -- letters+kernings
   if malglyphs[malcounter]==37 then malsize=malsize+1 end -- Only letters.
   else 
   malwrite=0 -- Stop analysing actual word, it has no meaning anymore.
   end -- stop searching

end -- for, malcounter

-- If we need some information from the Lua table...
--[[for allchars=1,#malglyphs do
   if maldraw then print(allchars, maldraw[allchars]) end
   end -- for, malheader
   ]]
end -- function, showme


-- This is the first run, we need data about nodes.
malglyphs={}; run=nil; counter=0
show_hyph(head)
showme()

-- This is the second run, we will highlight letters (and also kerning with an invisible pen :-) ).
malglyphs={}; run=1; counter=0
show_hyph(head)
showme()

return true -- Let's finish our work and send data back to a callback.
end -- major function, towork()
\end{luacode*}


% Some TeX commands for general use...
% A minimum of letters required in an unhyphenateable word to be highlighted.
\def\malactivateset#1{
   \luaexec{
   print("malmax "..#1)
   malmax=tonumber(#1) or 0
   }}

% This command activates a callback.
\def\malactivate{
   \directlua{luatexbase.add_to_callback("post_linebreak_filter",towork,"towork")}
   } % End of \activateme...

% This command deactivates a callback.
\def\maldeactivate{
   \directlua{luatexbase.remove_from_callback("post_linebreak_filter","towork")}
   } % End of \deactivateme...

% This text is an example for TeX.SX.
\def\maltext{\newpage
   Minimum of required letters: \the\malletters.\par
   Hello, the World!\par
   Here is some text without meaning.\par 
   \kant[1]\par
   } % End of \maltext...

% Small changes in paper mirror...
\rightskip=7cm
\parindent=0pt


\begin{document}
% A small example...
\malactivate % This command activates the algorithm...
\newcount\malletters 
\malletters=0 % Start with 0+1 letters, a common minimum.
\loop
   \advance\malletters by 1 % Try more letters.
   \malactivateset{\the\malletters} % Pass No. of letters to Lua.
   \maltext \relax % Text to be tested.
\ifnum\malletters<8 \repeat % Show us 8 pages.
\maldeactivate % This command deactivates the algorithm...
\end{document}

개념 증명의 예

관련 정보