# Is there any solution for highlighting text in CJK?

Is there any solution for highlighting texts or sentences in Chinese, Japanese, and Korean? I know none, at the moment.

But this will be changed, if someone would like to help me with CJK in LaTeX.

Problems:

1. If CJK text is highlighted by soul or other codes based on it, the highlight doesn't work at all.

I tried:

\documentclass[nofonts]{ctexbook}
\setCJKmainfont{SimSun}

\usepackage{soul}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{decorations.pathmorphing}

\makeatletter

\newcommand{\defhighlighter}[3][]{%
\tikzset{every highlighter/.style={color=#2, fill opacity=#3, #1}}%
}

\defhighlighter{yellow}{.5}

\newcommand{\highlight@DoHighlight}{
\fill [ decoration = {random steps, amplitude=1pt, segment length=15pt}
, outer sep = -15pt, inner sep = 0pt, decorate
, every highlighter, this highlighter ]
($(begin highlight)+(0,8pt)$) rectangle ($(end highlight)+(0,-3pt)$) ;
}

\newcommand{\highlight@BeginHighlight}{
\coordinate (begin highlight) at (0,0) ;
}

\newcommand{\highlight@EndHighlight}{
\coordinate (end highlight) at (0,0) ;
}

\newdimen\highlight@previous
\newdimen\highlight@current

\DeclareRobustCommand*\highlight[1][]{%
\tikzset{this highlighter/.style={#1}}%
\SOUL@setup
%
\def\SOUL@preamble{%
\begin{tikzpicture}[overlay, remember picture]
\highlight@BeginHighlight
\highlight@EndHighlight
\end{tikzpicture}%
}%
%
\def\SOUL@postamble{%
\begin{tikzpicture}[overlay, remember picture]
\highlight@EndHighlight
\highlight@DoHighlight
\end{tikzpicture}%
}%
%
\def\SOUL@everyhyphen{%
\discretionary{%
\SOUL@setkern\SOUL@hyphkern
\SOUL@sethyphenchar
\tikz[overlay, remember picture] \highlight@EndHighlight ;%
}{%
}{%
\SOUL@setkern\SOUL@charkern
}%
}%
%
\def\SOUL@everyexhyphen##1{%
\SOUL@setkern\SOUL@hyphkern
\hbox{##1}%
\discretionary{%
\tikz[overlay, remember picture] \highlight@EndHighlight ;%
}{%
}{%
\SOUL@setkern\SOUL@charkern
}%
}%
%
\def\SOUL@everysyllable{%
\begin{tikzpicture}[overlay, remember picture]
\path let \p0 = (begin highlight), \p1 = (0,0) in \pgfextra
\global\highlight@previous=\y0
\global\highlight@current =\y1
\endpgfextra (0,0) ;
\ifdim\highlight@current < \highlight@previous
\highlight@DoHighlight
\highlight@BeginHighlight
\fi
\end{tikzpicture}%
\the\SOUL@syllable
\tikz[overlay, remember picture] \highlight@EndHighlight ;%
}%
\SOUL@
}
\makeatother

\begin{document}
本条所说的三日期间与第98条规定的三日期间在计算上采同样的规则（请参考第98条的释义部分），期间的开始均不是以扣押命令的发出为标准，而是以扣押的生效为准。\highlight[red]{对邮件的扣押，以邮政服务机构收到扣押命令，邮件开始处于被截留的状态，视为扣押的生效（Pfeiffer S471 Rn4）}，期间由此开始。期间的开始计算同样适用第42条的规定。
但与第98条不同的是，第98条的三日期间只是向法官提出追认照准的申请的期间，而本条则是收到法官追认照准的期间。邮政服务机构如果在三日内没收到法官的追认，检察官的扣押命令失效，毋需再向检察官交出邮件。但邮件如果已经被交出的，则暂时不被返还，仍可保留在检察官处。如果在三日期满后法官又追认照准的，视为法官作出了新的扣押命令（Meyer-Goßner S325 Rn7）。
\highlight[red]{如果法官在三日内不予照准的呢？如果在三日内没有追认，在三日后也没有作出追认的？如果法官在三日后作出不予照准的呢？六种情况}
\end{document}


TeX reported:

Package soul Error: Reconstruction failed.
See the soul package documentation for explanation.


If I ignore these errors and compile the TeX file, the highlighted texts became black squares.

2. If CJK text is highlighted by some code based on soul, the highlight works, but the text can not be broken across lines, and they are all in one line beyond the edge of pages.

eg:

\documentclass[nofonts]{ctexbook}
\setCJKmainfont{SimSun}

\usepackage{soul}
\usepackage{tikz}
\newcommand*{\yellowhl}[1]{%
\tikz[baseline]\node[rectangle, fill=yellow, rounded corners, inner sep=0.3mm,anchor=base]{#1};%
}

\begin{document}
本条所说的三日期间与第98条规定的三日期间在计算上采同样的规则（请参考第98条的释义部分），期间的开始均不是以扣押命令的发出为标准，而是以扣押的生效为准。\yellowhl{对邮件的扣押，以邮政服务机构收到扣押命令，邮件开始处于被截留的状态，视为扣押的生效（Pfeiffer S471 Rn4）}，期间由此开始。期间的开始计算同样适用第42条的规定。
但与第98条不同的是，第98条的三日期间只是向法官提出追认照准的申请的期间，而本条则是收到法官追认照准的期间。邮政服务机构如果在三日内没收到法官的追认，检察官的扣押命令失效，毋需再向检察官交出邮件。但邮件如果已经被交出的，则暂时不被返还，仍可保留在检察官处。如果在三日期满后法官又追认照准的，视为法官作出了新的扣押命令（Meyer-Goßner S325 Rn7）。
\yellowhl{如果法官在三日内不予照准的呢？如果在三日内没有追认，在三日后也没有作出追认的？如果法官在三日后作出不予照准的呢？六种情况}
\end{document}


Crying for help: does anyone know how to solve it?

-
My previous solution: tex.stackexchange.com/a/48549/2674 (It is also useful for CJK scripts) – Leo Liu Oct 7 '12 at 12:10

The code from this answer is available as a package

Version with tests for punctuation and \obeylines, the original simpler version as discussed in comments is at the end. It appears (from no knowledge other than the example here) that the CJK punctuation characters have wide side bearings in the font but the typesetter also adjusts the spacing giving stretchy space around them. As the highlighting boxes each character separately this removed almost all the flexibility in the line and resulted in over-full lines.

The second version tests for some punctuation characters and adds 1pt stretch/shrink space before or after them. This probably isn't the amount of space that the typesetter would do in the unhighlit case and I hope it doesn't make any cultural horrors, it's hard when you have no idea what the text means to get this right. In the original image at the end the last line is seen to be overfull in this new version the extra shrink around the ? allows the line to end flush with the right margin.

\documentclass[nofonts]{ctexbook}
\setCJKmainfont{SimSun}

\definecolor{lightblue}{rgb}{0,0,1}

\newcommand*{\cjkhl}[2]{{\def\xcjklhcolorbox{\colorbox{#1}}\xcjkhl#2\relax}}

\makeatletter

%look ahhead for the next character
\def\xcjkhl{\futurelet\tmp\xxcjkhl}

%helper macro to make leaders with a highlight box.
\fboxsep\z@\xcjklhcolorbox{\strut\kern.1pt%
\ifx\cjkhlbleeda\relax\else\kern\cjkhlbleeda\fi\relax}%
\ifx\cjkhlbleeda\relax\else\kern-\cjkhlbleeda\fi\relax}}

% leaders with a 1pt of stretch/shrink to put before or after punctuation

\def\@chkhlpar#1\fi\fi#2{\par\noindent\xcjkhl}

\def\@cjkhl@beforeafter#1{%
\ifx\tmp#1%
\@@yhlstretch
\let\@chkhlstretch\@@yhlstretch
\let\cjkhlpenalty\@highpenalty
\fi}

\def\@cjkhl@after#1{%
\ifx\tmp#1%
\let\@chkhlstretch\@@yhlstretch
\let\cjkhlpenalty\@highpenalty
\fi}

\def\@cjkhl@before#1{%
\ifx\tmp#1%
\@@yhlstretch
\let\cjkhlpenalty\@highpenalty
\fi}

\def\xxcjkhl{%
%look for a \par (from \obeylines)
\ifx\tmp\par\expandafter\@chkhlpar\fi
%look for a \relax to finish
\ifx\tmp\relax
\else
%by default do no stretch leaders after the character
\let\@chkhlstretch\relax
\let\cjkhlpenalty\z@
%these stretch before and after
\@cjkhl@beforeafter？%
\@cjkhl@beforeafter；%
% these stretch after
\@cjkhl@after，%
\@cjkhl@after。%
\@cjkhl@after）%
\@cjkhl@after》%
\@cjkhl@after”%
%these stretch before
\@cjkhl@before（%
\@cjkhl@before《%
\@cjkhl@before“%
% look for a space
\ifx\tmp\@sptoken
\xxxcjkhlsp
\else
%default case stick the current character in a box
\xxxcjkhl
\fi\fi}

%make a highlight leaders stretch/shrink as much as a normal word space.
\def\xxxcjkhlsp#1\fi\fi#2{%
\fi\fi
\xcjkhlleaders\hskip \fontdimen2\font  plus \fontdimen3\font minus \fontdimen4\font\relax
\xcjkhl#2}

%get out of a double \if test
\def\xxxcjkhl\fi\fi{%
\fi\fi
\@chkhl}

%The simple case box the current character and start looking for the next.
% bleed slightly on the right to avoid gaps showing
\let\cjkhlbleeda\relax
\def\cjkhlbleeda{.07pt}
\def\@chkhl#1{{%
\fboxsep\z@
\leavevmode\penalty\cjkhlpenalty
\xcjklhcolorbox{%
\strut#1\ifx\cjkhlbleeda\relax\else\kern\cjkhlbleeda\fi}}%
\ifx\cjkhlbleeda\relax\else\kern-\cjkhlbleeda\fi\relax
\@chkhlstretch
\xcjkhl}%

\makeatother

\begin{document}

\cjkhl{lightblue}{如果法官在三日内不予照准的呢？如果在三日内没有追认，在三日后也没有作出追认的？如果法官在三日后作出不予照准的呢？六种情况}

\bigskip
\hrule
\bigskip
\obeylines

（请参考第98条的释义部分），期间的开始均不是以扣押命令的发出为标准，而是以扣押的生效为准。\cjkhl{yellow}{对邮件的扣押，

\cjkhl{lightblue}{如果法官在三日内不予照准的呢？如

\end{document}


Original simple version:

This highlights each character separately so it gives sub-optimal kerning and breaks ligatures but this is presumably more of an issue for any alphabetic script within the highlight rather than for CJK characters.

Tested with xelatex. I hope the text isn't scrambled, I can't read it.

\documentclass[nofonts]{ctexbook}
\setCJKmainfont{SimSun}

\newcommand*{\yellowhl}[1]{\xyellowhl#1\relax}
\makeatletter

\def\xyellowhl{\futurelet\tmp\xxyellowhl}

\def\xxyellowhl{%
\ifx\tmp\relax
\else
\ifx\tmp\@sptoken
\xxxyellowhlsp
\else
\xxxyellowhl
\fi\fi}

\def\xxxyellowhlsp#1\fi\fi#2{%
\fi\fi
\hskip \fontdimen2\font  plus \fontdimen3\font minus \fontdimen4\font\relax
\xyellowhl#2}

\def\xxxyellowhl\fi\fi{%
\fi\fi
\@yhl}

\def\@yhl#1{{%
\fboxsep\z@
\leavevmode\penalty\z@\colorbox{yellow}{\strut#1}}%
\xyellowhl}%

\makeatother
\begin{document}

\yellowhl{如果法官在三日内不予照准的呢？如果在三日内没有追认，在三日后也没有作出追认的？如果法官在三日后作出不予照准的呢？六种情况}
\end{document}

-
Thank you for your help! It works well in CJK, and there only some tiny issues need to improve. 1. How to make paragraph obey the original lines in the highlighted part? Namely beginning a new line is a begin of new paragraph which can be made by ‘\obeylines’, and it doesn’t work here. At the moment once they are highlighted all the lines and paragraph are in one line who is highlighted. – WonderTree Oct 3 '12 at 9:04
2. When there are CJK punctuations in a highlighted line, the right end of lines will stand out of the right margin than other lines. I found that you have done twice highlighting behaviors in the Macro, how about for the CJK punctuations the first time highlight doesn’t do, or if there are some other way to resolve this? I know ‘\sloppy’ can resolve this, but I can’t use it in my tex on editor’s demands. – WonderTree Oct 3 '12 at 9:05
Here is the errors' pic bbs.ctex.org/data/attachment/forum/201210/03/… – WonderTree Oct 3 '12 at 9:17
Sorry, I don't catch what 'the tests on \tmp could look for that' means. Now I have to go out for some work, I will supply more info later. Thank you first! – WonderTree Oct 3 '12 at 9:21
Chinese punctuations, eg: ， 。 ； ： “ ” 、———— ‘ ’ 《 》【 】 ？ – WonderTree Oct 3 '12 at 9:27

A simpler solution:

\documentclass[fntef]{ctexart}
\usepackage{xcolor}
\usepackage{ulem}
\newcommand\hl{\bgroup\markoverwith
{\textcolor{yellow}{\rule[-.5ex]{2pt}{2.5ex}}}\ULon}

\begin{document}

\hl{汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字汉字

\end{document}


Note that fntef option is necessary (or use CJKulem for CJK package).

-
In this solution, how to make paragraph obey the original lines in the highlighted part? Namely beginning a new line is a begin of new paragraph which can be made by ‘\obeylines’, and it doesn’t work here. At the moment once they are highlighted all the lines and paragraph are in one line who is highlighted. – WonderTree Oct 8 '12 at 0:18