diff options
author | Karl Berry <karl@freefriends.org> | 2021-01-12 21:24:12 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2021-01-12 21:24:12 +0000 |
commit | 27346c71d2523f5f9c84602f857d59ce21f05b4f (patch) | |
tree | dfe90fef2e8f392006beaafff2839524261a113b /Master/texmf-dist/source/latex | |
parent | f457b191c09c01b2daa0aa5662cdce782b0fde96 (diff) |
pxpic (12jan21)
git-svn-id: svn://tug.org/texlive/trunk@57400 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/source/latex')
-rw-r--r-- | Master/texmf-dist/source/latex/pxpic/pxpic.dtx | 1022 |
1 files changed, 1022 insertions, 0 deletions
diff --git a/Master/texmf-dist/source/latex/pxpic/pxpic.dtx b/Master/texmf-dist/source/latex/pxpic/pxpic.dtx new file mode 100644 index 00000000000..5ece9f64902 --- /dev/null +++ b/Master/texmf-dist/source/latex/pxpic/pxpic.dtx @@ -0,0 +1,1022 @@ +% \iffalse meta-comment +% +% File: pxpic.dtx Copyright (C) 2021 Jonathan P. Spratte +% +% This work may be distributed and/or modified under the conditions of the +% LaTeX Project Public License (LPPL), either version 1.3c of this license or +% (at your option) any later version. The latest version of this license is in +% the file: +% +% http://www.latex-project.org/lppl.txt +% +% ------------------------------------------------------------------------------ +% +%<*driver>^^A>>= +\def\nameofplainTeX{plain} +\ifx\fmtname\nameofplainTeX\else + \expandafter\begingroup +\fi +\input l3docstrip.tex +\askforoverwritefalse +\preamble + +-------------------------------------------------------------- +pxpic -- draw pixel pictures +E-mail: jspratte@yahoo.de +Released under the LaTeX Project Public License v1.3c or later +See http://www.latex-project.org/lppl.txt +-------------------------------------------------------------- + +Copyright (C) 2021 Jonathan P. Spratte + +This work may be distributed and/or modified under the conditions of the +LaTeX Project Public License (LPPL), either version 1.3c of this license or +(at your option) any later version. The latest version of this license is in +the file: + + http://www.latex-project.org/lppl.txt + +This work is "maintained" (as per LPPL maintenance status) by + Jonathan P. Spratte. + +This work consists of the file pxpic.dtx +and the derived files pxpic.pdf + pxpic.sty + +\endpreamble +% stop docstrip adding \endinput +\postamble +\endpostamble +\generate{\file{pxpic.sty}{\from{pxpic.dtx}{pkg}}} +\ifx\fmtname\nameofplainTeX + \expandafter\endbatchfile +\else + \expandafter\endgroup +\fi +% +\ProvidesFile{pxpic.dtx}[2021-01-10 v1.0 draw pixel pictures] +\PassOptionsToPackage{full}{textcomp} +\documentclass{l3doc} +\RequirePackage[oldstylenums,nott]{kpfonts} +\usepackage{pxpic} +\input{glyphtounicode} +\pdfgentounicode=1 +\RequirePackage{listings} +\RequirePackage{booktabs} +\RequirePackage{array} +\RequirePackage{collcell} +\RequirePackage{xcolor} +\RequirePackage{caption} +\RequirePackage{microtype} +\RequirePackage{accsupp} +\RequirePackage{enumitem} +\lstset + { + ,flexiblecolumns=false + ,basewidth=.53em + ,gobble=2 + ,basicstyle=\fontfamily{jkp}\itshape + ,morekeywords=^^A + {^^A + \pxpic,\pxpicsetup + } + ,morecomment=[l]\% + ,commentstyle=\color[gray]{0.4} + ,literate={\{}{{\CodeSymbol\{}}{1} + {\}}{{\CodeSymbol\}}}{1} + ^^A,literate=*{<key>}{\key}{4}{<set>}{\set}{4} + } +\newcommand*\CodeSymbol[1]{\textbf{#1}} +\RequirePackage{randtext} +\let\metaORIG\meta +\protected\def\meta #1{\texttt{\metaORIG{#1}}} +\newcommand*\CS{\cs[no-index]} +\renewcommand*\thefootnote{\fnsymbol{footnote}} +\definecolor{pxpicred}{HTML}{9F393D} +\colorlet{pxpicgrey}{black!75} +\makeatletter +\newcommand*\pxpicname + {^^A + \texorpdfstring + {^^A + \mbox + {^^A + \BeginAccSupp{ActualText=pxpic}^^A + \href{https://github.com/Skillmon/ltx_pxpic}{\pxpiclogo}^^A + \EndAccSupp{}^^A + }^^A + } + {pxpic}^^A + } +\definecolor{expkvred}{HTML}{9F393D} +\colorlet{expkvgrey}{black!75} +\newcommand*\expkv + {^^A + \texorpdfstring + {^^A + \mbox + {^^A + \BeginAccSupp{ActualText=expkv}^^A + \href{https://github.com/Skillmon/tex_expkv} + {^^A + \rmfamily + \bfseries + {\color{expkvgrey}e\kern-.05em x\kern-.05em}^^A + \lower.493ex + \hbox{{\color{expkvgrey}P}\kern-.1em{\color{expkvred}k}}^^A + \kern-.18em{\color{expkvred}v}^^A + }^^A + \EndAccSupp{}^^A + }^^A + } + {expkv}^^A + } +\hypersetup{linkcolor=red!80!black,urlcolor=purple!80!black} +\DoNotIndex{\baselineskip,\begingroup,\bgroup} +\DoNotIndex{\csname} +\DoNotIndex{\def,\detokenize,\dimexpr} +\DoNotIndex{\egroup,\ekvdef,\ekvdefNoVal,\ekvifdefinedNoVal,\ekvletkv,\ekvparse} +\DoNotIndex{\ekvsetdef,\endcsname,\endgroup,\expandafter} +\DoNotIndex{\hbox,\hskip} +\DoNotIndex{\leavevmode,\let,\long,\lower} +\DoNotIndex{\newcommand,\newdimen} +\DoNotIndex{\PackageError,\protected,\ProvidesPackage} +\DoNotIndex{\relax,\RequirePackage} +\DoNotIndex{\@depth,\@height,\@ifdefinable,\@ifnextchar,\@ifundefined,\@width} +\DoNotIndex{\ekv@ifempty,\ekv@name,\z@} +\DoNotIndex{\color} +\DoNotIndex{\vbox,\vrule} +\@ifdefinable\gobbledocstriptag{\def\gobbledocstriptag#1>{}} +\makeatother +\newenvironment{options}[1][] + {% + \begin{description} + [ + style=nextline + ,font=\normalfont\ttfamily + ,labelindent=-.5\marginparwidth + ,labelwidth=\dimexpr.5\marginparwidth-5pt\relax + ,labelsep*=5pt + ,leftmargin=! + ,#1 + ]% + \renewenvironment{options}[1][] + {% + \begin{description} + [ + style=nextline + ,font=\normalfont\ttfamily + ,#1 + ]% + } + {\end{description}}% + } + {\end{description}} +\begin{document} + \title + {^^A + \texorpdfstring + {^^A + \Huge + \mbox + {^^A + \BeginAccSupp{ActualText=pxpic}^^A + \href{https://github.com/Skillmon/ltx_pxpic}{\pxpiclogo}^^A + \EndAccSupp{}^^A + }^^A + \\[\medskipamount] + \Large draw pixel pictures^^A + }{pxpic - draw pixel pictures}^^A + } + \date{2021-01-10 v1.0} + \author{Jonathan P. Spratte\thanks{\protect\randomize{jspratte@yahoo.de}}} + \DocInput{pxpic.dtx} +\end{document} +%</driver>^^A=<< +% \fi +% +% \maketitle +% \renewcommand*\thefootnote{\arabic{footnote}} +% +% \begin{abstract} +% \noindent\parfillskip=0pt +% With \pxpicname\ you draw pictures pixel by pixel. It was inspired by a +% \href{https://tex.stackexchange.com/a/63759/117050} +% {lovely post by Paulo Cereda}, +% among other things (most notably a beautiful duck) showcasing the use of +% characters from the Mario video games by Nintendo in \LaTeX. +% \end{abstract} +% +% \tableofcontents +% +% \begin{documentation}^^A>>= +% +% \section{Documentation} +% +% \subsection{Drawing pictures} +% +% \pxpicname\ supports different input modes, all of them have the same basic +% parsing behaviour. A \meta{pixel list} contains the pixel colours. The image +% is built line wise from top left to bottom right. Each row of pixels should be +% a single \TeX\ argument (so either just one token, or a group delimited by +% |{}|), and within each line each pixel in turn should be a single \TeX\ +% argument (so either just one token, or a group delimited by |{}|). Spaces and +% hence single newlines in the sources between \meta{pixel list} elements are +% ignored. The different modes are explained in \autoref{sec:modes}. The only +% disallowed token in the \meta{pixel list} is the control sequence +% \CS{pxpic@end} (plus the usual restrictions of \TeX\ so no unbalanced braces, +% no macros defined as \CS{outer}). +% +% There is a small caveat however: \pxpicname\ draws each pixel individually, +% and there is really no space between them, however some \textsc{pdf} viewers +% fail to display such adjacent lines correctly and leave small gaps (basically +% the same issue which packages like \pkg{colortbl} suffer from as well). In +% print this shouldn't be an issue, but some rasterisation algorithms employed +% by viewers and conversion tools have this deficit. +% +% \begin{function}{\pxpic} +% \begin{syntax} +% \cs{pxpic}\oarg{options}\marg{pixel list} +% \end{syntax} +% \meta{options} might be any options as listed in \autoref{sec:options}, and +% \meta{pixel list} is a list of pixels as described above. \cs{pxpic} parses +% the \meta{pixel list} and draws the corresponding picture. The result is +% contained in an \CS{hbox} and can be used wherever \TeX\ expects an +% \CS{hbox}. As a result, when you're in vertical mode a \cs{pxpic} will form +% a text line, to prevent this you can use \CS{leavevmode} before it. The +% \cs{pxpic} will be bottom aligned, you can change this using \CS{raisebox} +% (or, if you want, \TeX's \CS{raise} and \CS{lower} primitives). +% \end{function} +% +% \subsubsection{Examples} +% +% Since the above explanation of the \meta{pixel list} syntax might've been a +% bit cryptic, and a good documentation should contain examples (this doesn't +% claim this documentation is \emph{good}), well, here are some examples (you +% might need to take a look at \autoref{sec:options} and \autoref{sec:modes} to +% fully understand the examples). Examples in this section will use the +% following \CS{pxpicsetup}: +% +% \begingroup +% \footnotesize +% \begin{lstlisting} +% \pxpicsetup +% { +% mode = px +% ,colours = {k=black, r=[HTML]{9F393D}, g=green!75!black, b=[rgb]{0,0,1}} +% ,skip = . +% ,size = 10pt +% } +% \end{lstlisting} +% \endgroup +% +% \begingroup +% \pxpicsetup +% { +% mode = px +% ,colours = {k=black, r=[HTML]{9F393D}, g=green!75!black, b=[rgb]{0,0,1}} +% ,skip = . +% ,size = 10pt +% } +% +% We can draw a small cross rather easily:\par\nobreak +% \noindent +% \begin{minipage}[c]{.5\linewidth}\footnotesize +% \begin{lstlisting} +% \pxpic +% { +% {.k} +% {kkk} +% {.k} +% } +% \end{lstlisting} +% \end{minipage} +% \begin{minipage}[c]{.45\linewidth} +% \leavevmode +% \pxpic +% { +% {.k} +% {kkk} +% {.k} +% } +% \end{minipage} +% +% A small multicoloured grid:\par\nobreak +% \noindent +% \begin{minipage}[c]{.5\linewidth}\footnotesize +% \begin{lstlisting} +% \pxpic +% { +% {brgk} +% {kbrg} +% {gkbr} +% {rgkb} +% } +% \end{lstlisting} +% \end{minipage} +% \begin{minipage}[c]{.45\linewidth} +% \leavevmode +% \pxpic +% { +% {brgk} +% {kbrg} +% {gkbr} +% {rgkb} +% } +% \end{minipage} +% +% A heart (shamelessly copied example from \pkg{pixelart}):\par\nobreak +% \noindent +% \begin{minipage}[c]{.5\linewidth}\footnotesize +% \begin{lstlisting} +% \pxpic +% { +% {..rr.rr} +% {.rrrrrrr} +% {rrrrrrrrr} +% {rrrrrrrrr} +% {rrrrrrrrr} +% {.rrrrrrr} +% {..rrrrr} +% {...rrr} +% {....r} +% } +% \end{lstlisting} +% \end{minipage} +% \begin{minipage}[c]{.45\linewidth} +% \leavevmode +% \pxpic +% { +% {..rr.rr} +% {.rrrrrrr} +% {rrrrrrrrr} +% {rrrrrrrrr} +% {rrrrrrrrr} +% {.rrrrrrr} +% {..rrrrr} +% {...rrr} +% {....r} +% } +% \end{minipage} +% +% Using |mode=rgb| to draw a short coloured line:\par\nobreak +% \noindent +% \begin{minipage}[c]{.5\linewidth}\footnotesize +% \begin{lstlisting} +% \pxpic[mode=rgb]{{{1,0,1}{1,1,0}{0,1,1}}} +% \end{lstlisting} +% \end{minipage} +% \begin{minipage}[c]{.45\linewidth} +% \leavevmode +% \pxpic[mode=rgb]{{{1,0,1}{1,1,0}{0,1,1}}} +% \end{minipage} +% +% A multicoloured grid using skips and |mode=cmy|:\par\nobreak +% \noindent +% \begin{minipage}[c]{.5\linewidth}\footnotesize +% \begin{lstlisting} +% \pxpic[mode=cmy] +% { +% {{1,0,1} {1,1,0} {0,1,1} {} } +% {{} {1,0,1} {1,1,0} {0,1,1}} +% {{0,1,1} {} {1,0,1} {1,1,0}} +% {{1,1,0} {0,1,1} {} {1,0,1}} +% } +% \end{lstlisting} +% \end{minipage} +% \begin{minipage}[c]{.45\linewidth} +% \leavevmode +% \pxpic[mode=cmy] +% { +% {{1,0,1} {1,1,0} {0,1,1} {} } +% {{} {1,0,1} {1,1,0} {0,1,1}} +% {{0,1,1} {} {1,0,1} {1,1,0}} +% {{1,1,0} {0,1,1} {} {1,0,1}} +% } +% \end{minipage} +% +% Showing the difference between a skipped and a white pixel:\par\nobreak +% \noindent +% \begin{minipage}[c]{.5\linewidth}\footnotesize +% \begin{lstlisting} +% \pxpicsetup{colours = {w=white}} +% \colorbox{gray}{\pxpic{{bbb}{b.b}{bbb}}} +% \colorbox{gray}{\pxpic{{bbb}{bwb}{bbb}}} +% \end{lstlisting} +% \end{minipage} +% \begin{minipage}[c]{.45\linewidth} +% \pxpicsetup{colours = {w=white}} +% \colorbox{gray}{\pxpic{{bbb}{b.b}{bbb}}} +% \colorbox{gray}{\pxpic{{bbb}{bwb}{bbb}}} +% \end{minipage} +% +% \enlargethispage{1.1\baselineskip} +% A biggish example: Tux.\footnote{Source: +% \url{https://www.reddit.com/r/linux/comments/hwpm9j/tux_pixel_art_v10/}} I +% put two rows of pixels per code line to reduce the size a bit and the code is +% displayed tinily.\par\nobreak +% \noindent +% \begin{minipage}[c]{.5\linewidth}\tiny +% \begin{lstlisting} +% \pxpic +% [ +% size = 2.5pt +% ,colours = {:=orange, +% '=black!10, +% g=black!75, +% O=orange!80!black} +% ] +% { +% {...........gggg} {.........gggkkggg} +% {........ggkkkkkkkg} {........gkkkkkkkkg} +% {........kkkkkkkkkk} {.......gkk.kkkk.kkk} +% {.......gk.k.kk.k.kk} {.......gk.k.kk.k.kk} +% {.......gkkkkkkkkkkk} {.......gkkk::::kkkk} +% {.......gk::::::::kk} {.......gk.:kkkk:kkk} +% {......gkk..::::'kkkk} {......gkk....'''kkkk} +% {......gkk....''''kkk} {.....gkk.....''''kkkk} +% {.....gk.......''''kkk} {....gkk........'''kkkk} +% {....gkk........'''kkkk} {....gk..........''kkkk} +% {...gkkg.........'''kkkk} {...gkkkk........'''kkkk} +% {..OOOOkkk.......'''kOOOO} {..O::::kkk......'''O:::O} +% {.O::::::kk.....'''::::::O} {.O::::::kkk...''kk::::::O} +% {O:::::::kkk...'kkk:::::::O} {O:::::::kkk...'kkk:::::::O} +% {.O:::::::kkkkkkkk:::::::O} {..OO:::::kkkkkkkk:::::OO} +% {....OO::O.kkkkkk.O::OO} {......OOO........OOO} +% } +% \end{lstlisting} +% \end{minipage} +% \begin{minipage}[c]{.45\linewidth} +% \leavevmode +% \pxpic +% [ +% size = 2.5pt +% ,colours = {:=orange, +% '=black!10, +% g=black!75, +% O=orange!80!black} +% ] +% { +% {...........gggg} {.........gggkkggg} +% {........ggkkkkkkkg} {........gkkkkkkkkg} +% {........kkkkkkkkkk} {.......gkk.kkkk.kkk} +% {.......gk.k.kk.k.kk} {.......gk.k.kk.k.kk} +% {.......gkkkkkkkkkkk} {.......gkkk::::kkkk} +% {.......gk::::::::kk} {.......gk.:kkkk:kkk} +% {......gkk..::::'kkkk} {......gkk....'''kkkk} +% {......gkk....''''kkk} {.....gkk.....''''kkkk} +% {.....gk.......''''kkk} {....gkk........'''kkkk} +% {....gkk........'''kkkk} {....gk..........''kkkk} +% {...gkkg.........'''kkkk} {...gkkkk........'''kkkk} +% {..OOOOkkk.......'''kOOOO} {..O::::kkk......'''O:::O} +% {.O::::::kk.....'''::::::O} {.O::::::kkk...''kk::::::O} +% {O:::::::kkk...'kkk:::::::O} {O:::::::kkk...'kkk:::::::O} +% {.O:::::::kkkkkkkk:::::::O} {..OO:::::kkkkkkkk:::::OO} +% {....OO::O.kkkkkk.O::OO} {......OOO........OOO} +% } +% \end{minipage} +% +% Just for Paulo, a duck. Also, showing that the colour definitions in |mode=px| +% can be arbitrary tokens or multiple letters:\par\nobreak +% \noindent +% \begin{minipage}[c]{.5\linewidth}\tiny +% \begin{lstlisting} +% \pxpic[colours = {oo=orange, +% \ylw=yellow, +% \blk=black}, +% skip = \skp] +% { +% {\skp\skp\skp\ylw\ylw\ylw\ylw} +% {\skp\skp\ylw\ylw\ylw\ylw\ylw\ylw} +% {\skp\skp{oo}\ylw\blk\ylw\ylw\ylw} +% {{oo}{oo}{oo}\ylw\ylw\ylw\ylw\ylw} +% {\skp{oo}{oo}{oo}\ylw\ylw\ylw\skp\skp\skp\skp\skp\ylw} +% {\skp\skp\skp\ylw\ylw\ylw\ylw\ylw\ylw\ylw\skp\ylw\ylw} +% {\skp\skp\ylw\ylw\ylw\ylw\ylw\ylw\ylw\ylw\ylw\ylw\ylw} +% {\skp\ylw\ylw\ylw\ylw\ylw\ylw\ylw\ylw\skp\ylw\ylw} +% {\skp\ylw\ylw\skp\ylw\ylw\ylw\ylw\skp\ylw\ylw\ylw} +% {\skp\ylw\ylw\ylw\skp\skp\skp\skp\ylw\ylw\ylw} +% {\skp\skp\ylw\ylw\ylw\ylw\ylw\ylw\ylw\ylw} +% {\skp\skp\skp\skp\ylw\ylw\ylw\ylw\ylw} +% } +% \end{lstlisting} +% \end{minipage} +% \begin{minipage}[c]{.45\linewidth} +% \leavevmode +% \pxpic[colours = {oo=orange, +% \ylw=yellow, +% \blk=black}, +% skip = \skp] +% { +% {\skp\skp\skp\ylw\ylw\ylw\ylw} +% {\skp\skp\ylw\ylw\ylw\ylw\ylw\ylw} +% {\skp\skp{oo}\ylw\blk\ylw\ylw\ylw} +% {{oo}{oo}{oo}\ylw\ylw\ylw\ylw\ylw} +% {\skp{oo}{oo}{oo}\ylw\ylw\ylw\skp\skp\skp\skp\skp\ylw} +% {\skp\skp\skp\ylw\ylw\ylw\ylw\ylw\ylw\ylw\skp\ylw\ylw} +% {\skp\skp\ylw\ylw\ylw\ylw\ylw\ylw\ylw\ylw\ylw\ylw\ylw} +% {\skp\ylw\ylw\ylw\ylw\ylw\ylw\ylw\ylw\skp\ylw\ylw} +% {\skp\ylw\ylw\skp\ylw\ylw\ylw\ylw\skp\ylw\ylw\ylw} +% {\skp\ylw\ylw\ylw\skp\skp\skp\skp\ylw\ylw\ylw} +% {\skp\skp\ylw\ylw\ylw\ylw\ylw\ylw\ylw\ylw} +% {\skp\skp\skp\skp\ylw\ylw\ylw\ylw\ylw} +% } +% \end{minipage} +% +% Another example might be the definition of \CS{pxpiclogo} in +% \autoref{sec:implementation:pxpiclogo}. +% +% Who still needs \env{picture}-mode or complicated packages like +% \pkg{pstricks} or Ti\emph{k}Z with such pretty pictures? +% +% \endgroup +% +% \subsection{Setting options}\label{sec:options} +% +% To control its behaviour \pxpicname\ uses a key=value interface powered by +% \expkv. Options can be set either in the optional argument of +% \CS{pxpic} or with +% +% \begin{function}{\pxpicsetup} +% \begin{syntax} +% \cs{pxpicsetup}\marg{options} +% \end{syntax} +% Sets the \meta{options} locally to the current \TeX\ group. +% \end{function} +% +% \medskip\noindent +% Package options are not supported. +% +% \bigskip +% The available options are +% +% \begin{options} +% \item[colors] Define pixel colours for |mode=px|, see \autoref{sec:colours} +% for a description of the value's syntax. No pixel definitions are made by +% the package. +% \item[colours] \emph{see \texttt{colors}.} +% \item[ht] Set the height of the pixels. +% \item[mode] Set the used mode, see \autoref{sec:modes} for available modes. +% Initial value is |px|. +% \item[size] Set both |ht| and |wd|. Initial value is \the\pxpicHT. +% \item[skip] Define the value to be a skip (an empty space of width |wd|) in +% |mode=px|. No skip definitions are made by the package. +% \item[wd] Set the width of the pixels. +% \end{options} +% +% \subsubsection{Colour syntax}\label{sec:colours} +% +% In the value of the |colours| option you'll have to use the following syntax. +% Use a comma separated key=value list in which each key corresponds to a new +% pixel name for |mode=px|, and each value to the used colour. If the colour +% starts with an opening bracket use the complete value as is behind \CS{color}, +% else use the whole value as the first mandatory argument to \CS{color} with a +% set of braces added. For example to define |r| as the named colour |red|, and +% |x| as the colour |#abab0f| (in the \textsc{html} colour model) use: +% \begin{lstlisting} +% colours = {r=red, x=[HTML]{abab0f}} +% \end{lstlisting} +% +% \subsubsection{Available modes}\label{sec:modes} +% +% \begin{options} +% \item[px] +% As already mentioned, \pxpicname\ supports different modes of input. The +% easiest to use |mode| is |px|, in which each element of the \meta{pixel +% list} has been previously defined as either a coloured pixel (using the +% |colour| option) or as a skipped pixel (using the |skip| option, resulting +% in a fully transparent pixel). Each element will be \CS{detokenize}d, so +% (within \TeX's limitations) the name of a pixel can be arbitrary. This is +% the initial mode \pxpicname\ uses. But other options are available as +% well. +% \item[named] +% Another |mode| is |named|, in which each element of the \meta{pixel list} +% should be a named colour (or colour expression) known to \pkg{xcolor}. +% Each element will be used like so: |{\color{|\meta{element}|}\px}|. An +% exception is an element which is empty (|{}|), which will be a skipped +% pixel. +% \item[rgb, cmy, cmyk, hsb, Hsb, tHsb, gray, RGB, HTML, HSB, Gray, wave] +% The modes |rgb|, |cmy|, |cmyk|, |hsb|, |Hsb|, |tHsb|, |gray|, |RGB|, +% |HTML|, |HSB|, |Gray|, and |wave| correspond to the different colour +% models supported by \pkg{xcolor}. With these modes each element of the +% \meta{pixel list} will be the values in these colour models, so they'll be +% used like so: |{\color[|\meta{mode}|]{|\meta{element}|}\px}|. An +% exception is an element which is empty (|{}|), which will be a skipped +% pixel. +% \end{options} +% +% You can define additional modes selectable with the |mode| option using the +% macros |\pxpicnewmode| or |\pxpicsetmode|. +% +% \subsection{Other customisation macros} +% +% \begin{function}{\pxpicnewmode,\pxpicsetmode} +% \begin{syntax} +% \cs{pxpicnewmode}\marg{name}\marg{definition} +% \end{syntax} +% You can define your own modes with \cs{pxpicnewmode}. Inside +% \meta{definition} |#1| is the currently parsed item in the \CS{pxpic} +% \meta{pixel list}. You can output a pixel using \CS{px}, and skip a pixel +% using \CS{pxskip}. The pixel will use the currently active colour (so if you +% want to draw a red pixel you could use |{\color{red}\px}|). +% \cs{pxpicnewmode} will throw an error if you try to define a mode which +% already exists, \cs{pxpicsetmode} has no checks on the name. +% \end{function} +% +% \begin{function}{\pxpicforget} +% \begin{syntax} +% \cs{pxpicforget}\marg{px} +% \end{syntax} +% Undefines the \meta{px} definition for use in |mode=px| (or skip symbol) +% added with the |colours| (or |skip|) option. +% \end{function} +% +% \subsection{Other macros} +% +% \begin{function}{\px,\pxskip} +% Inside of a \CS{pxpic} the macro \cs{px} draws a pixel (of the currently +% active colour), and \cs{pxskip} leaves out a pixel (so this one pixel is +% fully transparent). Use this in the \meta{definition} of a mode in +% \CS{pxpicnewmode}. +% \end{function} +% +% \begin{variable}{\pxpicHT,\pxpicWD} +% These two are |dimen| registers storing the height and width of the pixels. +% \end{variable} +% +% \begin{function}{\pxpiclogo} +% \begin{syntax} +% \cs{pxpiclogo}\oarg{size} +% \end{syntax} +% This draws the logo of \pxpicname. The \meta{size} controls the pixel size. +% \end{function} +% +% \subsection{Miscellaneous} +% +% If you find bugs or have suggestions I'll be glad to hear about it, you can +% either open a ticket on Github (\url{https://github.com/Skillmon/ltx_pxpic}) +% or email me (see the first page). +% +% A similar package is \pkg{pixelart}, which, as of writing this, is described +% as a ``working draft'' by its author. \pxpicname\ wasn't intended as a direct +% competitor (I already started coding \pxpicname\ when I learned about +% \pkg{pixelart}'s existence), but I took inspiration from the ``Bugs, Ideas, +% Undefined behaviours'' section of \pkg{pixelart}'s documentation for the +% syntax of |mode=px|. +% +% +% \end{documentation}^^A=<< +% +% \begin{implementation}^^A>>= +% +% \gobbledocstriptag +%<*pkg> +% +% \clearpage +% +% \section{Implementation}^^A>>= +% +% Report who we are +% \begin{macrocode} +\ProvidesPackage{pxpic}[2021-01-10 v1.0 draw pixel pictures] +% \end{macrocode} +% and load dependencies +% \begin{macrocode} +\RequirePackage{xcolor} +\RequirePackage{expkv} +% \end{macrocode} +% \begin{variable}{\pxpicHT,\pxpicWD} +% These two variables store the height and width of a pixel. +% \begin{macrocode} +\@ifdefinable\pxpicHT{\newdimen\pxpicHT} +\@ifdefinable\pxpicWD{\newdimen\pxpicWD} +\pxpicHT=1pt +\pxpicWD=\pxpicHT +% \end{macrocode} +% \end{variable} +% +% +% \subsection{Options} +% +% We define the options using \expkv\ directly (no fancy options are involved +% and these are just a few anyway). +% +% The first few options are straight forward. We use \expkv's name space to +% actually store the |skip| and |px| definitions, hence we use +% \CS{ekvdefNoVal} in the code of |skip|. +% +% \begin{macrocode} +\protected\ekvdef{pxpic}{size} + {\pxpicHT=\dimexpr#1\relax\pxpicWD=\dimexpr#1\relax} +\protected\ekvdef{pxpic}{ht}{\pxpicHT=\dimexpr#1\relax} +\protected\ekvdef{pxpic}{wd}{\pxpicWD=\dimexpr#1\relax} +\protected\ekvdef{pxpic}{skip}{\ekvdefNoVal{pxpic@px}{#1}{\pxskip}} +% \end{macrocode} +% The |colours| option is parsed using \CS{ekvparse} and \CS{pxpic@setcolor}. +% \begin{macrocode} +\protected\ekvdef{pxpic}{colors}{\ekvparse\pxpic@noval\pxpic@setcolor{#1}} +\ekvletkv{pxpic}{colours}{pxpic}{colors} +% \end{macrocode} +% And the |mode| just checks whether the |mode| macro is defined and lets the +% auxiliary macro \CS{pxpic@parse@px} to the defined |mode|. +% \begin{macrocode} +\protected\ekvdef{pxpic}{mode} + {% + \@ifundefined{pxpic@parse@px@#1}% + {\pxpic@unknown@mode{#1}}% + {% + \expandafter\let\expandafter\pxpic@parse@px + \csname pxpic@parse@px@#1\endcsname + }% + } +% \end{macrocode} +% +% +% \subsection{User macros}\label{sec:implementation:pxpiclogo} +% +% \begin{macro}{\pxpic} +% \begin{macro}[internal]{\pxpic@} +% \CS{pxpic} expands directly to an opened \CS{hbox}, the auxiliary +% \CS{pxpic@} checks for the optional argument and inserts the rest of the +% code. We need to set \CS{baselineskip} to \CS{pxpicHT} so that the pixels +% are stacked vertically without gaps. \CS{pxpic@parse} will parse the +% \meta{pixel list} until \CS{pxpic@end} is hit. The final \CS{egroup} closes +% the \CS{hbox}. The row-wise output is done via a \CS{vbox} in which each +% pixel row will be wrapped inside an \CS{hbox}. +% \begin{macrocode} +\newcommand*\pxpic{\hbox\bgroup\pxpic@} +\newcommand\pxpic@[2][] + {% + \vbox + {% + \pxpicsetup{#1}% + \let\px\pxpic@px + \let\pxskip\pxpic@skip + \baselineskip\pxpicHT + \pxpic@parse#2\pxpic@end + }% + \egroup + } +% \end{macrocode} +% \end{macro} +% \end{macro} +% +% \begin{macro}{\pxpicsetup} +% Just directly defined to call \expkv's parser for the \pxpicname\ set. +% \begin{macrocode} +\ekvsetdef\pxpicsetup{pxpic} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\pxpiclogo} +% The logo is just a biggish pixel picture. The \CS{lower} will move it down a +% bit so that it appears correctly aligned on the baseline. Since the logo +% should be part of a normal sentence in most usages we put \CS{leavevmode} +% before it. Also we make sure that the |mode| and |px| definitions are +% correct. +% \begin{macrocode} +\newcommand*\pxpiclogo[1][.13ex] + {% + \begingroup + \pxpicHT\dimexpr#1\relax + \pxpicWD\pxpicHT + \leavevmode + \lower3.2\pxpicHT\pxpic + [mode=px,colours={o=[HTML]{9F393D},g=black!75},skip=.] + { + {............................................g} + {...........................................gggg} + {.oooo.......................gggg...........ggg} + {.ooooo...oo......oo...oo....ggggg...gg......g..........g} + {.ooooooooooo...ooooo..oooo..ggggggggggg...ggggg...ggggggg} + {..ooooo..oooo.ooooooooooo....ggggg..gggg.ggggggg.ggggggggg} + {...oooo..oooo....ooooo........gggg..gggg...gggg..gggg.ggg} + {...oooo..oooo.....oooo........gggg..gggg...gggg..gggg} + {.oooooo..oooo.....ooooo.....gggggg..gggg...gggg..gggg} + {oooooooooooo...ooooooooo...gggggggggggg....gggg..ggggggggg} + {o.oooooooo....ooooo.oooooo.g.gggggggg......ggggg..ggggggg} + {...ooo.o......o.oo...oo.......ggg.g.........gg......ggg} + {...ooo........................ggg} + {...ooo........................ggg} + {....o..........................g} + }% + \endgroup + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\pxpicforget} +% Straight forward, just let the |px| macro to an undefined macro. +% \begin{macrocode} +\newcommand\pxpicforget[1] + {\expandafter\let\csname\ekv@name{pxpic@px}{#1}N\endcsname\pxpic@undef} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}{\pxpicnewmode,\pxpicsetmode} +% These are pretty simple as well, the |new| variant will use \CS{newcommand} +% which will do the testing for us, the |set| variant uses \CS{def}. +% \begin{macrocode} +\protected\def\pxpicnewmode#1#2% + {\expandafter\newcommand\csname pxpic@parse@px@#1\endcsname[1]{#2}} +\protected\def\pxpicsetmode#1#2% + {\long\expandafter\def\csname pxpic@parse@px@#1\endcsname##1{#2}} +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Parser} +% +% \begin{macro}[internal]{\pxpic@ifend,\pxpic@ifempty,\pxpic@ifbracket} +% These are three helper macros. The first just gobbles everything until the +% next \CS{pxpic@end}, and we borrow a fast test for an empty argument from +% \expkv. The last can be used to check for an opening bracket if used like +% |\pxpic@ifbracket|\hskip0pt|\pxpic@end|\hskip0pt|#1.\pxpic@end|\hskip0pt +% |[]\pxpic@end|. +% \begin{macrocode} +\long\def\pxpic@ifend#1\pxpic@end{} +\let\pxpic@ifempty\ekv@ifempty +\long\def\pxpic@ifbracket#1\pxpic@end[#2]\pxpic@end{\pxpic@ifempty{#2}} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\pxpic@parse,\pxpic@done} +% The parsing loop is pretty simple, first check whether we're done, else open +% a new \CS{hbox} (which will form a row in the \CS{vbox} placed by +% \CS{pxpic@}) in which the inner parsing loop is run. Then call the next +% iteration. If we're done just gobble the remainder of the current iteration. +% \begin{macrocode} +\newcommand\pxpic@parse[1] + {% + \pxpic@ifend#1\pxpic@done\pxpic@end + \hbox{\pxpic@parseline#1\pxpic@end}% + \pxpic@parse + } +\long\def\pxpic@done\pxpic@end\hbox#1\pxpic@parse{} +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\pxpic@parseline,\pxpic@linedone} +% The line parsing loop also checks whether we're done, if not we place a +% pixel using the current definition of \CS{pxpic@parse@px} (which will be set +% by the current |mode|) and afterwards call the next iteration. If we're done +% we gobble the remainder of the current iteration and control goes back to +% \CS{pxpic@parse}. +% \begin{macrocode} +\newcommand\pxpic@parseline[1] + {% + \pxpic@ifend#1\pxpic@linedone\pxpic@end + \pxpic@parse@px{#1}% + \pxpic@parseline + } +\long\def\pxpic@linedone\pxpic@end\pxpic@parse@px#1\pxpic@parseline{} +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Modes} +% +% The modes define how a single element of the \meta{pixel list} is parsed. +% +% \begin{macro}[internal]{\pxpic@parse@px@px,\pxpic@parse@px} +% In the |px| mode we check whether the pixel is defined (using the name space +% of \expkv), if so call it, else throw an error and skip. Since this is also +% the initial |mode| we \CS{let} the auxiliary macro \CS{pxpic@parse@px} to +% this mode here. +% \begin{macrocode} +\newcommand\pxpic@parse@px@px[1] + {% + \ekvifdefinedNoVal{pxpic@px}{#1} + {\csname\ekv@name{pxpic@px}{#1}N\endcsname}% + {% + \pxpic@unknown@px{#1}% + \pxskip + }% + } +\let\pxpic@parse@px\pxpic@parse@px@px +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal]{\pxpic@parse@px@named} +% |named| just checks whether the skip is empty. If so skip, else call +% \CS{color} with the element and output a pixel. +% \begin{macrocode} +\newcommand\pxpic@parse@px@named[1] + {% + \pxpic@ifempty{#1} + {\pxskip} + {{\color{#1}\px}}% + } +% \end{macrocode} +% \end{macro} +% +% \begin{macro}[internal] +% { +% \pxpic@parse@px@rgb, +% \pxpic@parse@px@cmy, +% \pxpic@parse@px@cmyk, +% \pxpic@parse@px@hsb, +% \pxpic@parse@px@Hsb, +% \pxpic@parse@px@tHsb, +% \pxpic@parse@px@gray, +% \pxpic@parse@px@RGB, +% \pxpic@parse@px@HTML, +% \pxpic@parse@px@HSB, +% \pxpic@parse@px@Gray, +% \pxpic@parse@px@wave +% } +% The colour model modes are all the same in principle. They test for an empty +% element to introduce a skip, else they call \CS{color} with the respective +% colour model and output a pixel. We use the auxiliary \CS{pxpic@tmp} to do +% all those definitions and undefine it afterwards. +% \begin{macrocode} +\def\pxpic@tmp#1% + {% + \pxpicnewmode{#1}% + {% + \pxpic@ifempty{##1} + {\pxskip} + {{\color[#1]{##1}\px}}% + }% + } +\pxpic@tmp{rgb} +\pxpic@tmp{cmy} +\pxpic@tmp{cmyk} +\pxpic@tmp{hsb} +\pxpic@tmp{Hsb} +\pxpic@tmp{tHsb} +\pxpic@tmp{gray} +\pxpic@tmp{RGB} +\pxpic@tmp{HTML} +\pxpic@tmp{HSB} +\pxpic@tmp{Gray} +\pxpic@tmp{wave} +\let\pxpic@tmp\pxpic@undef +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Pixel and Skip} +% +% \begin{macro}[internal]{\pxpic@px,\pxpic@skip} +% The actual definition of pixels and skips is stored in macros to which the +% frontend macros \CS{px} and \CS{pxskip} will be let inside of \CS{pxpic}. +% \begin{macrocode} +\newcommand\pxpic@px{\vrule\@height\pxpicHT\@width\pxpicWD\@depth\z@} +\newcommand\pxpic@skip{\hskip\pxpicWD} +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Parser for colours} +% +% \begin{macro}[internal]{\pxpic@setcolor,\pxpic@setcolor@a,\pxpic@setcolor@b} +% First we test whether the colour starts with an opening bracket or not. +% Depending on that we either just put the colour after \CS{color}, or put +% braces around it (as it then is a colour expression for \pkg{xcolor} and +% just a single argument). \CS{pxpic@setcolor} defines a |px| in the name +% space of \expkv\ (this has a slight overhead during definition, but \expkv\ +% is fast in checking whether one of its keys is defined or not, and reduces +% the amount of code in this package). +% \begin{macrocode} +\newcommand\pxpic@setcolor[2] + {% + \pxpic@ifbracket\pxpic@end#2.\pxpic@end[]\pxpic@end + \pxpic@setcolor@a\pxpic@setcolor@b + {#1}{#2}% + } +\newcommand\pxpic@setcolor@a[2] + {\ekvdefNoVal{pxpic@px}{#1}{{\color{#2}\px}}} +\newcommand\pxpic@setcolor@b[2] + {\ekvdefNoVal{pxpic@px}{#1}{{\color#2\px}}} +% \end{macrocode} +% \end{macro} +% +% +% \subsection{Messages} +% +% \begin{macro}[internal]{\pxpic@noval,\pxpic@unknown@px,\pxpic@unknown@mode} +% These are just some macros throwing errors, nothing special here. +% \begin{macrocode} +\newcommand\pxpic@noval[1] + {\PackageError{pxpic}{Missing colour definition for name `\detokenize{#1}'}{}} +\newcommand\pxpic@unknown@px[1] + {\PackageError{pxpic}{Unknown pixel `\detokenize{#1}'. Skipping}{}} +\newcommand\pxpic@unknown@mode[1] + {\PackageError{pxpic}{Unknown mode `#1'}{}} +% \end{macrocode} +% \end{macro} +% +%^^A=<< +% +% \gobbledocstriptag +%</pkg> +% +% \end{implementation}^^A=<< +% +% \clearpage +% \PrintIndex +% +\endinput +% +^^A vim: ft=tex fdm=marker fmr=>>=,=<< |