From 3692808268baf9f2c56b28f61c266ef0efbb0fe6 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Thu, 17 Nov 2022 03:01:35 +0000 Subject: CTAN sync 202211170301 --- graphics/pgf/contrib/pixelart/CHANGELOG.md | 22 +- graphics/pgf/contrib/pixelart/README.md | 44 +- graphics/pgf/contrib/pixelart/pixelart.dtx | 654 ------------------ graphics/pgf/contrib/pixelart/pixelart.ins | 59 -- graphics/pgf/contrib/pixelart/pixelart.lua | 680 +++++++++++++++++++ graphics/pgf/contrib/pixelart/pixelart.pdf | Bin 152344 -> 231203 bytes graphics/pgf/contrib/pixelart/pixelart.sty | 179 +++++ graphics/pgf/contrib/pixelart/pixelart.tex | 990 ++++++++++++++++++++++++++++ graphics/pgf/contrib/pixelart/pixelart0.pdf | Bin 0 -> 152390 bytes graphics/pgf/contrib/pixelart/pixelart0.sty | 114 ++++ graphics/pgf/contrib/pixelart/pixelart0.tex | 454 +++++++++++++ 11 files changed, 2456 insertions(+), 740 deletions(-) delete mode 100644 graphics/pgf/contrib/pixelart/pixelart.dtx delete mode 100644 graphics/pgf/contrib/pixelart/pixelart.ins create mode 100644 graphics/pgf/contrib/pixelart/pixelart.lua create mode 100644 graphics/pgf/contrib/pixelart/pixelart.sty create mode 100644 graphics/pgf/contrib/pixelart/pixelart.tex create mode 100644 graphics/pgf/contrib/pixelart/pixelart0.pdf create mode 100644 graphics/pgf/contrib/pixelart/pixelart0.sty create mode 100644 graphics/pgf/contrib/pixelart/pixelart0.tex (limited to 'graphics/pgf') diff --git a/graphics/pgf/contrib/pixelart/CHANGELOG.md b/graphics/pgf/contrib/pixelart/CHANGELOG.md index 4a0fdfaee8..daf7e7e726 100644 --- a/graphics/pgf/contrib/pixelart/CHANGELOG.md +++ b/graphics/pgf/contrib/pixelart/CHANGELOG.md @@ -1,24 +1,38 @@ +* pixelart 1.0.0 (2022-11-16) + + * Full, backward incompatible, rewrite of `pixelart`, in Lua. + * Keep version 0 of `pixelart` as `pixelart0`. + + -- Louis Paternault + +* pixelart 0.3.0 (2022-11-16) + + * Renamed `pixelart` to `pixelart0`. + * Mark `pixelart0` as unmaintained. + + -- Louis Paternault + * pixelart 0.2.0 (2018-02-25) * Add a `draft` package option. - -- Louis Paternault + -- Louis Paternault * pixelart 0.1.2 (2018-01-13) * Fix bug: First line-break is now automatically ignored. * Minor documentation fixes and improvements. - -- Louis Paternault + -- Louis Paternault * pixelart 0.1.1 (2017-12-08) * Fix CTAN URLs. - -- Louis Paternault + -- Louis Paternault * pixelart 0.1.0 (2017-12-05) * First published version. - -- Louis Paternault + -- Louis Paternault diff --git a/graphics/pgf/contrib/pixelart/README.md b/graphics/pgf/contrib/pixelart/README.md index 471df069b2..47eb31b3b6 100644 --- a/graphics/pgf/contrib/pixelart/README.md +++ b/graphics/pgf/contrib/pixelart/README.md @@ -1,38 +1,36 @@ pixelart 🎨 A LaTeX package to draw pixel-art pictures ====================================================== -[![Sources](https://img.shields.io/badge/sources-pixelart-brightgreen.svg)](http://framagit.org/spalax/pixelart) -[![CTAN](https://img.shields.io/ctan/v/pixelart.svg)](http://ctan.org/pkg/pixelart) -[![Documentation](https://img.shields.io/badge/doc-pdf-brightgreen.svg)](http://mirrors.ctan.org/graphics/pixelart/pixelart.pdf) +![Example](https://framagit.org/spalax/pixelart/-/raw/v1.0.0/pixelart.png) - - -![Example](https://framagit.org/spalax/pixelart/raw/master/logo.png) - -It defines commands to convert a stream of bits (as characters `0` and `1`) to a -black-and-white picture. - -- [Usage and installation instruction](http://mirrors.ctan.org/graphics/pixelart/pixelart.pdf). -- Example: The picture above was produced using the following code. +- [Usage and installation instruction](http://mirrors.ctan.org/graphics/pgf/contrib/pixelart/pixelart.pdf). +- Example: The heart of the picture above was produced using the following code. ```latex -\bwpixelart[color=red]{ - 0011001100 - 0111111110 - 1111111111 - 1111111111 - 1111111111 - 0111111110 - 0011111100 - 0001111000 - 0000110000 +\pixelart[ + colors={ + 1=red, + 2={red!50!black}, + 3={pink}, + 4={pink!50!red}, + }, + ]{% + ..12..12.. + .13411112. + 1341111112 + 1341111112 + 1341111112 + .11111112. + ..111112.. + ...1112... + ....12.... } ``` License ------- -*Copyright 2018 Louis Paternault* +*Copyright 2018-2022 Louis Paternault* This work may be distributed and/or modified under the conditions of the LaTeX Project Public License, either version 1.3 of this license or (at your option) diff --git a/graphics/pgf/contrib/pixelart/pixelart.dtx b/graphics/pgf/contrib/pixelart/pixelart.dtx deleted file mode 100644 index 472831348b..0000000000 --- a/graphics/pgf/contrib/pixelart/pixelart.dtx +++ /dev/null @@ -1,654 +0,0 @@ -% \iffalse meta-comment -% Copyright 2017-2018 Louis Paternault -% -% This work may be distributed and/or modified under the -% conditions of the LaTeX Project Public License, either version 1.3 -% of this license or (at your option) any later version. -% The latest version of this license is in -% http://www.latex-project.org/lppl.txt -% and version 1.3 or later is part of all distributions of LaTeX -% version 2005/12/01 or later. -% -% This work has the LPPL maintenance status `maintained'. -% -% The Current Maintainer of this work is Louis Paternault -% -% This work consists of the files pixelart.dtx and pixelart.ins -% and the derived file pixelart.sty. -% \fi -% -% \iffalse -%<*driver> -\ProvidesFile{pixelart.dtx} -% -% -%\NeedsTeXFormat{LaTeX2e} -%\ProvidesPackage{pixelart} -%<*package> - [2018/02/25 v0.2.0 A package to draw pixel-art pictures] -% -% -%<*driver> -\documentclass{ltxdoc} -\EnableCrossrefs -\CodelineIndex -\RecordChanges -\usepackage{hyperref} -\usepackage{pixelart} -\usepackage{listings} -\usepackage{numprint} -\lstset{ - language=[LaTeX]TeX, - numbers=left, - numberstyle=\tiny, - backgroundcolor=\color{yellow!20}, - basicstyle=\small\color{black}\ttfamily, - keywordstyle=\color{blue!80}\sffamily, - commentstyle=\color{olive}, - stringstyle=\color{red}, -} -\usepackage{textcomp} -\usepackage{fontspec} -\usepackage[english]{babel} -% Smiley command published by percusse on https://tex.stackexchange.com/a/58913 -\newcommand{\smiley}{\tikz[baseline=-0.75ex, black]{ - \draw circle (2mm); - \node[fill,circle,inner sep=0.5pt] (left eye) at (135:0.8mm) {}; - \node[fill,circle,inner sep=0.5pt] (right eye) at (45:0.8mm) {}; - \draw (-145:0.9mm) arc (-120:-60:1.5mm); -} -} -\begin{document} -\DocInput{pixelart.dtx} -\end{document} -% -% \fi -% -% \CheckSum{0} -% \CharacterTable -% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z -% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z -% Digits \0\1\2\3\4\5\6\7\8\9 -% Exclamation \! Double quote \" Hash (number) \# -% Dollar \$ Percent \% Ampersand \& -% Acute accent \' Left paren \( Right paren \) -% Asterisk \* Plus \+ Comma \, -% Minus \- Point \. Solidus \/ -% Colon \: Semicolon \; Less than \< -% Equals \= Greater than \> Question mark \? -% Commercial at \@ Left bracket \[ Backslash \\ -% Right bracket \] Circumflex \^ Underscore \_ -% Grave accent \` Left brace \{ Vertical bar \| -% Right brace \} Tilde \~} -% -% \GetFileInfo{pixelart.dtx} -% -% \DoNotIndex{\#,\$,\%,\&,\@,\\,\{,\},\^,\_,\~,\ ,\!,\(,\),\,} -% \DoNotIndex{\@bwpa@newline} -% \DoNotIndex{\begin} -% \DoNotIndex{\coordinate} -% \DoNotIndex{\end, \else} -% \DoNotIndex{\fill, \fi} -% \DoNotIndex{\ifpixelart@draft} -% \DoNotIndex{\makeatletter, \makeatother} -% \DoNotIndex{\newcommand, \newif} -% \DoNotIndex{\ProcessPgfPackageOptions, \pgfkeys, \pgfkeyssetvalue, \pgfkeysvalueof, \pgfparserdef, \pgfparserparse, \pgfparserswitch} -% \DoNotIndex{\raisebox, \RequirePackage} -% \DoNotIndex{\space} -% \DoNotIndex{\tikz} -% \DoNotIndex{\usepgfmodule, \usetikzlibrary} -% -% \title{ -% \begin{tikzpicture} -% \tikzbwpixelart[scale=.037]{(-1.05, .14)}{% -% 1111110001100000000000000000001110000010000000000000001000 -% 0110011001100000000000000000000110000111000000000000011000 -% 0110011000000000000000000000000110001101100000000000011000 -% 0110011011100110000110011111000110011000110110111001111110 -% 0111110001100011001100110001100110011000110011101100011000 -% 0110000001100001111000111111100110011111110011001100011000 -% 0110000001100000110000110000000110011000110011000000011000 -% 0110000001100001111000110000000110011000110011000000011000 -% 0110000001100011001100110001100110011000110011000000011011 -% 1111000011110110000110011111001111011000110111100000001110 -% }% -% \draw (0, 0) node[opacity=0]{\LARGE PixelArt}; -% \end{tikzpicture}\thanks{ -% This document corresponds to \textsf{pixelart}~\fileversion, dated \filedate. -% Home page, bug requests, etc. at \url{http://framagit.org/spalax/pixelart} -% }\\A package to draw pixel-art pictures.} -% \author{Louis Paternault\\ \texttt{spalax+ctan(at)gresille(dot)org}} -% -% \maketitle -% -% \begin{abstract} -% This package defines macros to draw pixel-art pictures using \LaTeX{}. -% \end{abstract} -% -% \setcounter{tocdepth}{2} -% \tableofcontents -% -% \section{Introduction} -% This document introduces the \textsf{pixelart} package, used to draw pixel-art pictures. -% -% \subsection{License} -% This work may be distributed and/or modified under the -% conditions of the \LaTeX Project Public License, either version 1.3 -% of this license or (at your option) any later version. -% -% Further information can be found in the |.dtx| file used to build this -% document. -% -% \subsection{Overview} -% Installation instruction are given in section \ref{sec:install}. -% Documentation about how to use this package (and examples) is given in section -% \ref{sec:usage}. Section \ref{sec:bugs} lists some known bugs and -% limitations, and implementation is given in section -% \ref{sec:implementation}. -% -% \section{Download and Install} -% \label{sec:install} -% -% \subsection{\textsc{Gnu}/Linux Distribution} -% -% If applicable, the easiest way to get |pixelart| working is by installing it by your distribution package. In Debian (and Ubuntu, and surely other distributions that inherit from Debian) it is packaged in |texlive-pictures| since version \texttt{2017.20180103-1}. So you can install it by running: -% -% \begin{quote} -% |sudo apt install texlive-pictures| -% \end{quote} -% -% \subsection{LaTeX distribution} -% -% This package is included both in \TeX{}Live and MiK\TeX{}. It can be installed using their respective package managers. -% -% \subsection{Manual installation} -% -% \begin{itemize} -% \item Download the lastest archive : -% \begin{description} -% \item[Stable version] \url{http://mirrors.ctan.org/graphics/pixelart.zip} -% \item[Development version] \url{https://framagit.org/spalax/pixelart/repository/archive.zip?ref=master} -% \end{description} -% \item Unzip the archive. -% \item If you got the archive from CTAN (stable version), move file \texttt{tex/latex/pixelart/pixelart.sty} in a \LaTeX{} path. -% \item If you got the development version, |cd| to the main archive directory, and run |latex pixelart.ins| to build |pixelart.sty|. Move this file into a \LaTeX{} path. -% \end{itemize} -% -% \section{Usage} -% \label{sec:usage} -% -% \subsection{Package options} -% \changes{v0.2.0}{2018/01/25}{Add package option \texttt{draft}.} -% -% This package has a single package option: |draft|. If this option is set (\lstinline|\usepackage[draft]{pixelart}|), pixel-art pictures are ignored. This can make compilation \emph{way, way} faster\footnote{On a document I am writing, containing a lot of pixel-art pictures, option |draft| makes compilation time go from 6 minutes to 22 seconds.}. -% -% A downside is that since pixel-art pictures are ignored, this can mess up your document layout. A nicer option would be to have option |draft| guess the pixel-art size, and display a dummy picture with the same size. Patches are welcome! \smiley -% -% \subsection{Macros} -% -% This package defines two macros : |\bwpixelart|\footnote{\texttt{$\backslash{}$bwpixelart} stands for \emph{b}lack and \emph{w}hite \emph{pixel art}, although \emph{color and transparent pixel art} would be more accurate.}, used to insert a pixel-art picture, and |\tikzbwpixelart|, which has the same purpose, excepted that it is called from within a |tikzpicture| environment. -% -% \subsubsection{\textbackslash\texttt{bwpixelart}} -% \DescribeMacro{\bwpixelart} -% To insert a pixel-art picture in your text, use : -% \begin{center} -% \lstinline|\bwpixelart|\oarg{color, raise, scale}\marg{pixels} -% \end{center} -% Its optional arguments are: -% \begin{description} -% \item[color=black] Foreground color (the background is transparent); -% \item[scale=1] Scale. By default, a pixel is the size of a |tikzpicture| default unit, which is probably bigger than what you want. -% \item[raise=0pt] Raise the picture. By default, the bottom of the picture is on the baseline. You might want to lower it a little by giving this option a negative argument. -% \end{description} -% -% Its mandatory argument is the picture pixels, as |0|'s and |1|'s. Line breaks in this argument are interpreted as line breaks in the pixel art pictures. How spaces are interpreted is undefined (see section \ref{ssec:spaces} for more information). -% -% For instance, this heart -% \bwpixelart[color=red, scale=.05, raise=-1ex]{% -% 001101100 -% 011111110 -% 111111111 -% 111111111 -% 111111111 -% 011111110 -% 001111100 -% 000111000 -% 000010000 -% } -% was drawn using the following code: -% -% \iffalse -%<*example> -% \fi -% \begin{lstlisting} - \bwpixelart[color=red, scale=.05, raise=-1ex]{% - 001101100 - 011111110 - 111111111 - 111111111 - 111111111 - 011111110 - 001111100 - 000111000 - 000010000 - } -\end{lstlisting} -% \iffalse -% -% \fi -% -% \subsubsection{\textbackslash\texttt{tikzbwpixelart}} -% \DescribeMacro{\tikzbwpixelart} -% The second macro, |\tikzbwpixelart| is almost identical to the first one, excepted that it is meant to be called from inside a |tikzpicture| environment. Actually, \lstinline|\bwpixelart{0101}| is more or less equivalent to calling : -% \iffalse -%<*example> -% \fi -% \begin{lstlisting} -\begin{tikzpicture} - \tikzbwpixelart{(0, 0)}{0101} -\end{tikzpicture} -\end{lstlisting} -% \iffalse -% -% \fi - -% The signature of this macro is : -% \begin{center} -% \lstinline|\tikzbwpixelart|\oarg{color, scale}\marg{coordinates}\marg{pixels} -% \end{center} -% Its optional arguments are |color| and |scale|, used to set the color and scale of the picture. -% -% Its first mandatory argument is the coordinate of the top left corner of the picture; the second one is the list of pixels (using the same syntax as the |\bwpixelart| macro). -% -% For instance, this heart -%\begin{tikzpicture}[scale=.05, baseline=-1em] -% \fill[red] (5, -4) circle (6.5); -% \tikzbwpixelart{(0, 0)}{% -% 0011001100 -% 0111111110 -% 1111111111 -% 1111111111 -% 1111111111 -% 0111111110 -% 0011111100 -% 0001111000 -% 0000110000 -%} -%\end{tikzpicture} -% was drawn using the following code: -% -% \iffalse -%<*example> -% \fi -% \begin{lstlisting} -\begin{tikzpicture}[scale=.05, baseline=-1em] - \fill[red] (5, -4) circle (6.5); - \tikzbwpixelart{(0, 0)}{% - 0011001100 - 0111111110 - 1111111111 - 1111111111 - 1111111111 - 0111111110 - 0011111100 - 0001111000 - 0000110000 -} -\end{tikzpicture} -\end{lstlisting} -% \iffalse -% -% \fi -% -%\section{Bugs, Ideas, Undefined behaviours} -%\label{sec:bugs} -% -% I have great ideas about what this package could do, but: -% \begin{itemize} -% \item I do not need them; -% \item I am not sure there is a huge \emph{need} for some pixel-art package; -% \item I have a full-time job, my wife has a far-more-than-full-time job, my daugther \emph{is} a full-time job, so I have very little time to hack… -% \end{itemize} -% -% So, I am listing here some known bugs, undefined behaviours, limitations. You, random passer-by, will be greatly welcome if you were to fix or implement stuff listed in this section. \smiley -% -% \subsection{Missing \texttt{\textbackslash{}pixelart} macro} -% -% There is no |\pixelart| macro. This is on purpose: given that this package is more or less a working draft, I did not want to register a badly designed |\pixelart| macro. This means that some folk wanting to improve this package can extand the |\bwpixelart| macro and use the name |\pixelart| to fix my design mistakes. -% -% \subsection{It's insanely slooooow.} -% -% That's it. It takes alomst 30 seconds to compile a document containing only a $128\times128$ picture (about \numprint{16000} pixels). I have no idea how to fix it. Good luck. -% -% \subsection{Black and white} -% -% Right now, it is black and white only (or, to be more accurate, any single color on a transparent background). -% -% One \emph{could} produce colored pixel-art pictures, but… it's complicated. For instance, this heart (borrowed from the Django project\footnote{\url{https://www.djangoproject.com/}}): -% -% \definecolor{violet1}{RGB}{247, 176, 207} -% \definecolor{violet2}{RGB}{238, 33, 120} -% \definecolor{violet3}{RGB}{214, 45, 117} -% \definecolor{violet4}{RGB}{217, 25, 92} -% \definecolor{violet5}{RGB}{173, 29, 69} -% \begin{center} -% \begin{tikzpicture}[scale=.1] -% \tikzbwpixelart[color=violet1]{(0, 0)}{% -% 0000000 -% 0000010 -% } -% \tikzbwpixelart[color=violet2]{(0, 0)}{% -% 0000000 -% 0110100 -% 0000000 -% 0010100 -% 0000000 -% 0001000 -% } -% \tikzbwpixelart[color=violet3]{(0, 0)}{% -% 0000010 -% 0000000 -% 1000010 -% 0000000 -% 0001000 -% } -% \tikzbwpixelart[color=violet4]{(0, 0)}{% -% 0010100 -% 1001000 -% 0110100 -% 0001010 -% 0010100 -% } -% \tikzbwpixelart[color=violet5]{(0, 0)}{% -% 0100000 -% 0000001 -% 0001001 -% 0100000 -% } -% \end{tikzpicture} -% \end{center} -% -% could be produced using the following code. Basically (given that colors |violet1| to |violet5| have been correctly defined), we stack up several single-color pixel-art pictures. -% -% \iffalse -%<*example> -% \fi -% \begin{lstlisting} -\begin{tikzpicture}[scale=.1] - \tikzbwpixelart[color=violet1]{(0, 0)}{% - 0000000 - 0000010 - } - \tikzbwpixelart[color=violet2]{(0, 0)}{% - 0000000 - 0110100 - 0000000 - 0010100 - 0000000 - 0001000 - } - \tikzbwpixelart[color=violet3]{(0, 0)}{% - 0000010 - 0000000 - 1000010 - 0000000 - 0001000 - } - \tikzbwpixelart[color=violet4]{(0, 0)}{% - 0010100 - 1001000 - 0110100 - 0001010 - 0010100 - } - \tikzbwpixelart[color=violet5]{(0, 0)}{% - 0100000 - 0000001 - 0001001 - 0100000 - } -\end{tikzpicture} -\end{lstlisting} -% \iffalse -% -% \fi -% -% One could imagine a simpler syntax: we assign several colors to characters, and we use |1|, |2|, |3|, etc. as the pixels to define the picture. This would give the following code. -% -% \iffalse -%<*example> -% \fi -% \begin{lstlisting} -\begin{tikzpicture}[scale=.1] - \tikzpixelart[colors={ - 1=violet1, - 2=violet2, - 3=violet3, - 4=violet4, - 5=violet5, - }]{(0, 0)}{% - 0540430 - 4224215 - 3445435 - 0524240 - 0043400 - 0002000 - } -\end{tikzpicture} -\end{lstlisting} -% \iffalse -% -% \fi -% -% Once again, patches are welcome! \smiley{} -% -% \subsection{Spaces} -%\label{ssec:spaces} -% -% Spaces are interpreted as line breaks. For instance, this heart -% \bwpixelart[scale=.03, raise=-1pt]{% -% 0011001100 0111111110 1111111111 -% 1111111111 1111111111 0111111110 -% 0011111100 0001111000 0000110000 -% } -% could be written as : -% \iffalse -%<*example> -% \fi -% \begin{lstlisting} -\bwpixelart[scale=.03, raise=-1pt]{% - 0011001100 0111111110 1111111111 - 1111111111 1111111111 0111111110 - 0011111100 0001111000 0000110000 -} -\end{lstlisting} -% \iffalse -% -% \fi -% -% This will work (right now), but is an undefined behaviour, and might change in a later version without prior notice. -% -% \subsection{Uneven lines} -% -% Right now, lines do not \emph{have} to have the same number of characters. For instance, the following heart -% \bwpixelart[scale=.03, raise=-1pt]{% -% 00110011 -% 011111111 -% 1111111111 -% 1111111111 -% 1111111111 -% 011111111 -% 00111111 -% 0001111 -% 000011 -%} -% could be written as : -% -% \iffalse -%<*example> -% \fi -% \begin{lstlisting} -\bwpixelart[scale=.03, raise=-1pt]{% - 00110011 - 011111111 - 1111111111 - 1111111111 - 1111111111 - 011111111 - 00111111 - 0001111 - 000011 -} -\end{lstlisting} -% \iffalse -% -% \fi -% -% This is an undefined behaviour and might raise an error in the future. -% -% \section{Implementation} -% \label{sec:implementation} -% -% Load some packages. -% \begin{macrocode} -\RequirePackage{pgf} -\RequirePackage{pgfopts} -\usepgfmodule{parser} -\RequirePackage{tikz} -\usetikzlibrary{calc} -\RequirePackage{pgfkeys} -\RequirePackage{etoolbox} - -% \end{macrocode} -% -% Let the nasty stuff begin. -% -% \begin{macrocode} -\makeatletter - -% \end{macrocode} -% -% Parse package options. -% -% \begin{macrocode} -\newif\ifpixelart@draft -\pgfkeys{ - /PIXELART/.cd, - draft/.is if=pixelart@draft, - draft=false, -} -\ProcessPgfPackageOptions{/PIXELART} -% \end{macrocode} -% -% Define macro arguments -% -% \begin{macrocode} -\pgfkeys{ - /PIXELART/BWPIXELART/.is family, - /PIXELART/BWPIXELART, - scale/.value required, - scale/.code={\pgfkeyssetvalue{/PIXELART/BWPIXELART/scale}{#1}}, - scale=1, - raise/.code={\pgfkeyssetvalue{/PIXELART/BWPIXELART/raise}{#1}}, - raise/.value required, - raise=0pt, - color/.value required, - color/.code={\pgfkeyssetvalue{/PIXELART/BWPIXELART/color}{#1}}, - color=black, -} - -\pgfkeys{ - /PIXELART/TIKZBWPIXELART/.is family, - /PIXELART/TIKZBWPIXELART, - scale/.value required, - scale/.code={\pgfkeyssetvalue{/PIXELART/TIKZBWPIXELART/scale}{#1}}, - scale=1, - color/.value required, - color/.code={\pgfkeyssetvalue{/PIXELART/TIKZBWPIXELART/color}{#1}}, - color=black, -} - -% \end{macrocode} -% -% Define argument parser, parsing the sequence of 0 and 1 defining the pixel art. -% -% \begin{macrocode} -\pgfparserdef{@bwpixelart}{initial}{blank space \space}{ - \@bwpa@newline -} -\pgfparserdef{@bwpixelart}{initial}{the character 0}{ - \coordinate (@pixelart) at ($(@pixelart) + (1, 0)$); -} -\pgfparserdef{@bwpixelart}{initial}{the character 1}{ - \fill (@pixelart) rectangle ++(1, 1); - \coordinate (@pixelart) at ($(@pixelart) + (1, 0)$); -} -\pgfparserdef{@bwpixelart}{initial}{the letter @}{ - \pgfparserswitch{final} -} - -\newcommand{\@bwpa@newline}{ - \coordinate (@pixelart) at ($(@pixelart@startline) + (0, -1)$); - \coordinate (@pixelart@startline) at (@pixelart); -} - -% \end{macrocode} -% -% \begin{macro}{\bwpixelart} -% \changes{v0.1.2}{2018/01/13}{First line-break of pixelart argument is now automatically ignored.} -% Define |\bwpixelart|, used to draw black-and-white pixelart. -% \begin{macrocode} -\newcommand{\bwpixelart}[2][]{{% - \pgfkeys{/PIXELART/BWPIXELART, #1}% - \raisebox{\pgfkeysvalueof{/PIXELART/BWPIXELART/raise}}{% - \tikz[ - scale=\pgfkeysvalueof{/PIXELART/BWPIXELART/scale}, - ]{ - \tikzbwpixelart[% - color=\pgfkeysvalueof{/PIXELART/BWPIXELART/color}, - ]{(0, 0)}{#2} - }% - }% -}} - -% \end{macrocode} -% \end{macro} -% \begin{macro}{\tikzbwpixelart} -% Define |\tikzbwpixelart|, used to draw black-and-white pixelart from inside a |tikzpicture| environment. -% \begin{macrocode} -\newcommand{\tikzbwpixelart}[3][]{ - \pgfkeys{/PIXELART/TIKZBWPIXELART, #1} - \ifpixelart@draft - % Draft mode. Nothing to parse, nothing to show! - \else - \begin{scope}[shift={#2}] - \begin{scope}[#1] - \coordinate (@pixelart) at (0, 1); - \coordinate (@pixelart@startline) at (@pixelart); - - \pgfparserparse{@bwpixelart} - #3 @ - \end{scope} - \end{scope} - \fi -} - -% \end{macrocode} -% That's all, folks! -% \begin{macrocode} -\makeatother - -% \end{macrocode} -% \end{macro} -% -% \changes{v0.1.0}{2017/12/05}{First published version.} -% -% \addcontentsline{toc}{section}{Change History} -% \PrintChanges -% -% \StopEventually{% -% \addcontentsline{toc}{section}{Index} -% \PrintIndex -% } -% \Finale -\endinput diff --git a/graphics/pgf/contrib/pixelart/pixelart.ins b/graphics/pgf/contrib/pixelart/pixelart.ins deleted file mode 100644 index add23f88ee..0000000000 --- a/graphics/pgf/contrib/pixelart/pixelart.ins +++ /dev/null @@ -1,59 +0,0 @@ -%% Copyright 2017 Louis Paternault -%% -%% This work may be distributed and/or modified under the -%% conditions of the LaTeX Project Public License, either version 1.3 -%% of this license or (at your option) any later version. -%% The latest version of this license is in -%% http://www.latex-project.org/lppl.txt -%% and version 1.3 or later is part of all distributions of LaTeX -%% version 2005/12/01 or later. -%% -%% This work has the LPPL maintenance status `maintained'. -%% -%% The Current Maintainer of this work is Louis Paternault -%% -%% This work consists of the files pixelart.dtx and pixelart.ins -%% and the derived file pixelart.sty. - -\input{docstrip} - -\keepsilent -\usedir{tex/latex/pixelart} - -\preamble -Copyright 2017 Louis Paternault - -This work may be distributed and/or modified under the -conditions of the LaTeX Project Public License, either version 1.3 -of this license or (at your option) any later version. -The latest version of this license is in - http://www.latex-project.org/lppl.txt -and version 1.3 or later is part of all distributions of LaTeX -version 2005/12/01 or later. - -This work has the LPPL maintenance status `maintained'. - -The Current Maintainer of this work is Louis Paternault - -This work consists of the files pixelart.dtx and pixelart.ins -and the derived file pixelart.sty. -\endpreamble - -\generate{\file{pixelart.sty}{\from{pixelart.dtx}{package}}} - -\obeyspaces -\Msg{****************************************************} -\Msg{* *} -\Msg{* To finish the installation you have to move the *} -\Msg{* following file into a directory searched by TeX: *} -\Msg{* *} -\Msg{* pixelart.sty *} -\Msg{* *} -\Msg{* To produce the documentation run the file *} -\Msg{* pixelart.dtx through LaTeX. *} -\Msg{* *} -\Msg{* Happy TeXing! *} -\Msg{* *} -\Msg{****************************************************} - -\endbatchfile diff --git a/graphics/pgf/contrib/pixelart/pixelart.lua b/graphics/pgf/contrib/pixelart/pixelart.lua new file mode 100644 index 0000000000..97a76d8f76 --- /dev/null +++ b/graphics/pgf/contrib/pixelart/pixelart.lua @@ -0,0 +1,680 @@ +require("lualibs-lpeg") +local luakeys = require("luakeys") + +pixelart = { + _debug = false, + _counter = 0, +} + +-------------------------------------------------------------------------------- +--[[ Debug on/off +--]] + +local function pixelart_setpixelartdebug(flag) + luakeys.opts.debug = flag + pixelart._debug = flag +end + +pixelart.setpixelartdebug = pixelart_setpixelartdebug +pixelart.setpixelartdebug = pixelart_setpixelartdebug + +-------------------------------------------------------------------------------- +--[[ Print +--]] + +local function tex_sprint(text) + tex.sprint(text) + if pixelart._debug then + io.write(text) + end +end + +local function tex_print(text) + tex.print(text) + if pixelart._debug then + io.write(text, "\n") + end +end + +-------------------------------------------------------------------------------- +--[[ Define and use colors +-- ]] +pixelart._colors = {} + +local function pixelart_parsecolors(argument) + return luakeys.parse( + argument, + { + naked_as_value = true, + hooks = { + keys = function(key, value, depth, current, result) + return tostring(key), value + end, + } + } + ) +end + +local function pixelart_newpixelartcolors(name, argument) + if pixelart._colors[name] == nil then + pixelart._colors[name] = pixelart_parsecolors(argument) + else + error(string.format("Error: Colors '%s' is already defined.", name)) + end +end + +local function pixelart_renewpixelartcolors(name, argument) + pixelart._colors[name] = pixelart_parsecolors(argument) +end + +pixelart.newpixelartcolors = pixelart_newpixelartcolors +pixelart.renewpixelartcolors = pixelart_renewpixelartcolors + +-- Default color sets +pixelart._colors["explicit"] = {} + +pixelart._colors["RGB"] = { + R = "red", + G = "green", + B = "blue", + W = "white", + K = "black" +} + +pixelart._colors["BW"] = { + ["0"] = "white", + ["1"] = "black", +} + +pixelart._colors["gray"] = { + ["0"] = "white", + ["1"] = "white!89!black", + ["2"] = "white!78!black", + ["3"] = "white!67!black", + ["4"] = "white!56!black", + ["5"] = "white!44!black", + ["6"] = "white!33!black", + ["7"] = "white!22!black", + ["8"] = "white!11!black", + ["9"] = "black", +} + +pixelart._colors["mono"] = {} +for _, char in pairs(string.explode("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", "")) do + pixelart._colors["mono"][char] = "" +end + + +-------------------------------------------------------------------------------- +--[[ Options +--]] + +local ALGORITHMS = {squares = true, stack = true} + +local function parse(str, default) + local parser = luakeys.define({ + tikz = {}, + colors = { + process = function(value, input, result, unknown) + -- If argument is a string, convert numeric keys into strings + if type(value) ~= "table" then + return value + end + + local converted = {} + for k, v in pairs(value) do + converted[tostring(k)] = v + end + return converted + end, + }, + margin = { + data_type = "number", + default = 0, + always_present = true, + }, + style = { + data_type = "string", + default = "pixelart", + always_present = true, + }, + squares = { + exclusive_group = "algo", + }, + stack = { + exclusive_group = "algo", + }, + draft = { + data_type = "boolean", + }, + }) + + options = parser(str, { + defaults = default, + }) + + -- Algo option + local algo = nil + for key, value in pairs(ALGORITHMS) do + if options[key] then + algo = key + end + end + if not algo then + options[pixelart._default_algo[1]] = pixelart._default_algo[2] + end + + -- Convert Tikz option back to string + if type(options.tikz) == type({}) then + options.tikz = luakeys.render(options.tikz) + end + + return options +end + +local DEFAULT = {colors = "mono"} +local function pixelart_setpixelartdefault(str) + pixelart._default = parse(str, DEFAULT) + + for key, value in pairs(pixelart._default) do + if ALGORITHMS[key] then + pixelart._default_algo = {key, value} + pixelart._default[key] = nil + end + end +end + +pixelart._default = {colors = "mono"} +pixelart._default_algo = {"stack", {}} +pixelart.setpixelartdefault = pixelart_setpixelartdefault + +-------------------------------------------------------------------------------- +--[[ Parse pixelart string +--Parse arguments, and build a table of tables. +--]] +-- +local lineRE = lpeg.Ct( + -- Regular expression to match a line of colors + ( + (lpeg.P("{") * lpeg.C((lpeg.P(1) - lpeg.S("{}"))^0) * lpeg.P("}")) + + + lpeg.C((lpeg.P(1) - lpeg.S("{}"))) + )^0 +) + +local function str2arrays(str) + -- Turn the \pixelart{} argument into a table (of lines) of tables (of colors). + + -- Trim string: remove leading and trailing whitespaces + str = str:gsub("^%s*(.-)%s*$", "%1") + + -- Turn it into a table (which is called "array" not to clash with the "table" library) + local array = {} + for k, line in ipairs(string.explode(str, " ")) do + array[k] = lineRE:match(line) + end + + -- Ensure each row has the same number of columns + local length = 0 + for k, line in ipairs(array) do + if #line > length then + length = #line + end + end + for k, line in ipairs(array) do + if #line < length then + for i=#line+1, length do + line[i] = false + end + end + end + + -- Flip array so that flipped[x][y] gives the pixel with coordinates (x, y), in the standard frame + local flipped = {} + for y, line in ipairs(array) do + for x, color in ipairs(array[y]) do + if y == 1 then + flipped[x] = {} + end + flipped[x][#array - y + 1] = color + end + end + + return flipped +end + +-------------------------------------------------------------------------------- +--[[ Color tools +--]] +local function color2color(colors, color) + -- Convert a color (as given by the user) into a color (usable by TikZ). + if color == "." or not color then + -- Transparent pixel: do not print anything + return nil + elseif colors[color] and colors[color] ~= "" then + -- A color has been defined: use it + return string.format("color=%s", colors[color]) + elseif colors[color] and colors[color] == "" then + -- An empty color has been defined: use the default TikZ color + return "" + else + -- No color has been defined: use the argument as the TikZ color + return color + end +end + +-------------------------------------------------------------------------------- +-- Turn pixelart string into TikZ code, using the SQUARES algorithm + +local function pixelart_body_squares(array, colors, options) + -- Draw the tikz pixels, as a set of squares. + + tex_print(string.format( + [[\clip ({0-%s}, {0-%s}) rectangle (%s, %s); ]], + options.margin, + options.margin, + #array + options.margin, + #array[1] + options.margin + )) + + for x, column in ipairs(array) do + for y, color in ipairs(column) do + color = color2color(colors, color) + + --------------------- + -- Which pixel size? + local overlap + if type(options.squares) == type({}) then + overlap = options.squares["overlap"] or "0" + else + overlap = "0" + end + + --------------------- + -- At last, we can display the pixel… + if color ~= nil then + tex_print(string.format([[\fill[%s, %s] (%s, %s) rectangle ++(1+%s, 1+%s);]], + options.style, + color, + string.format("{%s-%s}", x-1, overlap), + string.format("{%s-%s}", y-1, overlap), + 2*overlap, + 2*overlap + )) + end + end + end +end + +-------------------------------------------------------------------------------- +-- Turn pixelart string into TikZ code, using the STACK algorithm + +local function remove_zone(write, coord, read) + -- Remove the zone of the pixel `coord` + -- If both write and read are present (they are expected to be 2D-arrays of the same size, then read zones from `read`, and remove them from `write`. + + -- Default values for options + if read == nil then + read = write + end + if colorblind == nil then + colorblind = false + end + + local originalcolor = read[coord[1]][coord[2]] + local samecolor = function(color) return color == originalcolor end + + -- Go! + local stack = {} + table.insert(stack, coord) + while #stack ~= 0 do + local current = table.remove(stack) + for _, neighbour in pairs({ + {current[1]-1, current[2]}, + {current[1]+1, current[2]}, + {current[1], current[2]-1}, + {current[1], current[2]+1}, + }) do + if ( + neighbour[1] >= 1 and neighbour[1] <= #read -- First coordinate inside the array + and + neighbour[2] >= 1 and neighbour[2] <= #read[1] -- Second coordinate inside the array + and + write[neighbour[1]][neighbour[2]] -- Not processed yet + and + samecolor(read[neighbour[1]][neighbour[2]]) -- Same color + ) then + table.insert(stack, neighbour) + end + end + write[current[1]][current[2]] = false + end +end + +local border_transitions = { + westtop = { + tests = { + {1, 1}, + {1, 0}, + }, + next = { + ["true true"] = { + step = {1, 1}, + state = "northleft", + mark = {0, 0}, + }, + ["false true"] = { + step = {1, 0}, + state = "westtop", + mark = nil, + }, + ["true false"] = { + step = {0, 0}, + state = "southright", + mark = {1, 1}, + }, + ["false false"] = { + step = {0, 0}, + state = "southright", + mark = {1, 1}, + }, + }, + }, + northleft = { + tests = { + {-1, 1}, + {0, 1}, + }, + next = { + ["true true"] = { + step = {-1, 1}, + state = "eastbottom", + mark = {1, 0}, + }, + ["true false"] = { + step = {0, 0}, + state = "westtop", + mark = {0, 1}, + }, + ["false true"] = { + step = {0, 1}, + state = "northleft", + mark = nil, + }, + ["false false"] = { + step = {0, 0}, + state = "westtop", + mark = {0, 1}, + }, + }, + }, + southright = { + tests = { + {0, -1}, + {1, -1}, + }, + next = { + ["true true"] = { + step = {1, -1}, + state = "westtop", + mark = {0, 1}, + }, + ["false true"] = { + step = {0, 0}, + state = "eastbottom", + mark = {1, 0}, + }, + ["true false"] = { + step = {0, -1}, + state = "southright", + mark = nil, + }, + ["false false"] = { + step = {0, 0}, + state = "eastbottom", + mark = {1, 0}, + }, + }, + }, + eastbottom = { + tests = { + {-1, 0}, + {-1, -1}, + }, + next = { + ["true true"] = { + step = {-1, -1}, + state = "southright", + mark = {1, 1}, + }, + ["false true"] = { + step = {0, 0}, + state = "northleft", + mark = {0, 0}, + }, + ["true false"] = { + step = {-1, 0}, + state = "eastbottom", + mark = nil, + }, + ["false false"] = { + step = {0, 0}, + state = "northleft", + mark = {0, 0}, + }, + }, + }, +} + +local function iter_border(array, start, colorblind) + -- If colorblind==true, all colors are considered the same (that is, a pixel is either transparent or colored, with no difference between the colors) + local samecolor + if colorblind then + samecolor = function(current, test) + if ( + current[1] + test[1] < 1 + or + current[1] + test[1] > #array + ) then + return false + end + color = array[current[1] + test[1]][current[2] + test[2]] + if color == nil or color == false then + return false + end + return ( + color == "." and array[start[1]][start[2]] == "." + ) or ( + color ~= "." and array[start[1]][start[2]] ~= "." + ) + end + else + samecolor = function(current, test) + if ( + current[1] + test[1] < 1 + or + current[1] + test[1] > #array + ) then + return false + end + color = array[current[1] + test[1]][current[2] + test[2]] + return color == array[start[1]][start[2]] + end + end + + local current = {start[1], start[2]} + local state = "northleft" + + return function() + while true do + tests = border_transitions[state].tests + local transition = border_transitions[state].next[string.format( + "%s %s", + samecolor(current, tests[1]), + samecolor(current, tests[2]) + )] + state = transition.state + current = { + current[1] + transition.step[1], + current[2] + transition.step[2] + } + if transition.mark then + if current[1] == start[1] and current[2] == start[2] and state == "northleft" then + return + else + return { + current[1] + transition.mark[1], + current[2] + transition.mark[2], + } + end + end + end + end +end + +local function iter_unprocessed_zones(array) + -- Iterate coordinates of pixels that haven't been processed yet (their value is not false) + local x = 1 + local y = 1 + + return function() + while not array[x][y] do + x = x + 1 + if x > #array then + x = 1 + y = y + 1 + if y > #array[1] then + return + end + end + end + return {x, y} + end +end + +local function pixelart_body_stack(array, colors, options) + -- The first argument is an array of lines, each of them being an array of colors (i.e. color of the first pixel of the line, color of the second pixel of the line, etc). + -- Some "colors" have meaning: + -- - false (the boolean): pixel has already been processed + -- - "." (the character dot): pixel is transparent + -- - anything else: the color of the pixel + + if #array == 0 then + return + end + + tex_print([[\begin{scope}[even odd rule] ]]) + + -- Clip away transparent zones + tex_print(string.format( + [[\clip ({0-%s}, {0-%s}) rectangle (%s, %s) ]], + options.margin, + options.margin, + #array + options.margin, + #array[1] + options.margin + )) + + for x = 1, #array do + for y = 1, #array[x] do + if array[x][y] == "." then + tex_print(string.format("(%s, %s) rectangle ++(1, 1) ", x-1, y-1)) + end + end + end + + tex_print(";") + + -- Draw color zones + for current in iter_unprocessed_zones(array) do + local color = color2color(colors, array[current[1]][current[2]]) + if color == nil then + -- Nothing to do: transparent zone + else + tex_sprint(string.format([[\fill[%s, %s] (%s, %s) ]], options.style, color, current[1]-1, current[2]-1)) + for coord in iter_border(array, current, false) do + tex_sprint(string.format([[ -- (%s, %s) ]], coord[1]-1, coord[2]-1)) + end + tex_print(string.format([[ -- cycle ;]])) + end + remove_zone(array, {current[1], current[2]}) + end + + tex_print([[\end{scope} ]]) +end + +-------------------------------------------------------------------------------- +-- Functions pixelart() and tikzpixelart() + +local function pixelart_body(str, options) + -- Debug + pixelart._counter = pixelart._counter + 1 + if pixelart._debug then + io.write("\n%", str, "\n") + io.write("% pixelart ", pixelart._counter, ", file ", status.filename, ", input line ", tex.inputlineno, "\n") + else + io.write("(pixelart ", pixelart._counter, ", file ", status.filename, ", input line ", tex.inputlineno) + end + + -- Colors + local colors + if type(options.colors) == "table" then + colors = options.colors + else + colors = pixelart._colors[options.colors] + end + + if (pixelart._draft or options.draft) and options.draft ~= false then + local array = str2arrays(str) + tex_print(string.format( + [[ \draw[pattern=checkerboard] (0, 0) rectangle (%s, %s); ]], + #array, #array[1] + )) + elseif options.stack then + pixelart_body_stack(str2arrays(str), colors, options) + else -- options.squares is the default + pixelart_body_squares(str2arrays(str), colors, options) + end + + if pixelart._debug then + -- Nothing + else + io.write(")") + end +end + +local function pixelart_tikzpixelart(coord, str, options) + -- Parse options + local options = parse(options, pixelart._default) + + if options.tikz then + tex_sprint(string.format([[\begin{scope}[%s] ]], options.tikz)) + end + tex_print(string.format( + [[\begin{scope}[shift={%s}] ]], + coord + )) + + pixelart_body(str, options) + + tex_print([[\end{scope} ]]) + if options.tikz then + tex_print([[\end{scope} ]]) + end +end + +local function pixelart_pixelart(str, options) + -- Parse options + local options = parse(options, pixelart._default) + -- Tikz environment + tex_print([[\begin{tikzpicture}]]) + if options.tikz then + tex_sprint(string.format("[%s]", options.tikz)) + end + + pixelart_body(str, options) + + tex_print([[\end{tikzpicture}]]) +end + +pixelart.pixelart = pixelart_pixelart +pixelart.tikzpixelart = pixelart_tikzpixelart diff --git a/graphics/pgf/contrib/pixelart/pixelart.pdf b/graphics/pgf/contrib/pixelart/pixelart.pdf index a651a085fe..2a66d842aa 100644 Binary files a/graphics/pgf/contrib/pixelart/pixelart.pdf and b/graphics/pgf/contrib/pixelart/pixelart.pdf differ diff --git a/graphics/pgf/contrib/pixelart/pixelart.sty b/graphics/pgf/contrib/pixelart/pixelart.sty new file mode 100644 index 0000000000..52b90e4afc --- /dev/null +++ b/graphics/pgf/contrib/pixelart/pixelart.sty @@ -0,0 +1,179 @@ +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{pixelart} + +\RequirePackage{iftex} +\ifluatex + % Great! +\else + \PackageError{pixelart}{This package requires LuaTeX}{If you want to draw pixel-art pictures without LuaTeX, you can use either pixelart0 (outdated version of pixelart, bundled with this package), or pxpic} +\fi + +\RequirePackage{luacode} +\RequirePackage{tikz} +\usetikzlibrary{patterns} + +\luadirect{dofile("pixelart.lua")} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Package options +\DeclareOption{draft}{\luadirect{pixelart._draft = true}} +\ProcessOptions + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Default style +\tikzset{pixelart/.style={}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Wrappers to Lua functions + +\newcommand{\pixelart}[2][]{\luadirect{pixelart.pixelart("\luatexluaescapestring{#2}", "\luatexluaescapestring{#1}")}} +\newcommand{\tikzpixelart}[3][]{\luadirect{pixelart.tikzpixelart("\luatexluaescapestring{#2}", "\luatexluaescapestring{#3}", "\luatexluaescapestring{#1}")}} +\newcommand{\newpixelartcolors}[2]{\luadirect{pixelart.newpixelartcolors("\luatexluaescapestring{#1}", "\luatexluaescapestring{#2}")}} +\newcommand{\renewpixelartcolors}[2]{\luadirect{pixelart.renewpixelartcolors("\luatexluaescapestring{#1}", "\luatexluaescapestring{#2}")}} +\newcommand{\setpixelartdefault}[1]{\luadirect{pixelart.setpixelartdefault("\luatexluaescapestring{#1}")}} +\newcommand{\setpixelartdebugon}{\luadirect{pixelart.setpixelartdebug(true)}} +\newcommand{\setpixelartdebugoff}{\luadirect{pixelart.setpixelartdebug(false)}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Logos + +\makeatletter +\newcommand{\pixelartlogo}[1][ + colors={ + A=red, + B=orange, + C=yellow, + D=green, + E=cyan, + F=blue, + G=purple, + 1=red, + 2={red!50!black}, + 3={pink}, + 4={pink!50!red}, + }, + stack, + ]{% + \begin{tikzpicture}[scale={\f@size/400}] + \draw (34, 0) node[opacity=0, anchor=south, inner sep=0pt]{\texttt{Pixel Art}}; + \tikzpixelart[#1]{(0, 0)}{ + AAAABB...CC...................FFE...............A...............E... + .BA..AB..BC....................FF...12..12.....BBB.............DD... + .BB..AA........................GF..13411112...CC.BB............CD... + .CB..BA.AAB..BC....DD..EEEFF...GG.1341111112.DC...BB.BA.AAB..BCCCCD. + .CCCBB...AA...BB..CC..DD...EF..FG.1341111112.DD...CC..BBA.AB...BC... + .DC......BA....BBBC...DDDDEEE..FF.1341111112.EDDDDCC..BB..AA...BB... + .DD......BB.....BB....CC.......EF..11111112..EE...DD..CC.......AB... + .ED......CB....AAAB...CC.......EE...111112...FE...DD..CC.......AA... + .EE......CC...BB..AA..BB...CD..DE....1112....FF...EE..DD.......BA.AA + FFEE....DDCC.CB....AA..BBBCC..DDDD....12.....GF...EE.EDDD.......BBA. + } + \end{tikzpicture}% +} + +\newcommand{\pixelartheart}[1][ + colors={ + 1=red, + 2={red!50!black}, + 3={pink}, + 4={pink!50!red}, + }, + tikz={ + scale={\f@size/300}, + baseline=.1em, + }, + stack, + ]{% + \pixelart[#1]{ + ..12..12.. + .13411112. + 1341111112 + 1341111112 + 1341111112 + .11111112. + ..111112.. + ...1112... + ....12.... + }% +} + +\newcommand{\pixelartname}[1][ + colors={ + A=red, + B=orange, + C=yellow, + D=green, + E=cyan, + F=blue, + G=purple, + }, + stack, + ]{% + \begin{tikzpicture}[scale={\f@size/400}] + \draw (28, 0) node[opacity=0, anchor=south, inner sep=0pt]{\texttt{PixelArt}}; + \tikzpixelart[#1]{(0, 0)}{ + AAAABB...CC...................FFE.....D...............B... + .BA..AB..BC....................FF....EDD.............AB... + .BB..AA........................GF...EE.ED............AA... + .CB..BA.AAB..BC....DD..EEEFF...GG..FF...EE.DD.CCC..BBBAAA. + .CCCBB...AA...BB..CC..DD...EF..FG..GF...EE..DDD.CC...BB... + .DC......BA....BBBC...DDDDEEE..FF..GGGFFFF..EE..DD...CB... + .DD......BB.....BB....CC.......EF..FG...FF..EE.......CC... + .ED......CB....AAAB...CC.......EE..FF...GG..FF.......DC... + .EE......CC...BB..AA..BB...CD..DE..EF...GG..FF.......DD.CC + FFEE....DDCC.CB....AA..BBBCC..DDDD.EE...FF.GGGF.......DDD. + } + \end{tikzpicture}% +} + +\newcommand{\pixelartlogobw}[1][colors=mono, stack]{% + \begin{tikzpicture}[scale={\f@size/400}] + \draw (33, 0) node[opacity=0, anchor=south, inner sep=0pt]{\texttt{PixelArt}}; + \tikzpixelart[#1]{(0, 0)}{ + 111111...11...................111...............1...............1... + .11..11..11....................11...11..11.....111.............11... + .11..11........................11..11111111...11.11............11... + .11..11.111..11....11..11111...11.1111111111.11...11.11.111..111111. + .11111...11...11..11..11...11..11.1111111111.11...11..111.11...11... + .11......11....1111...1111111..11.1111111111.1111111..11..11...11... + .11......11.....11....11.......11..11111111..11...11..11.......11... + .11......11....1111...11.......11...111111...11...11..11.......11... + .11......11...11..11..11...11..11....1111....11...11..11.......11.11 + 1111....1111.11....11..11111..1111....11.....11...11.1111.......111. + } + \end{tikzpicture}% +} + +\newcommand{\pixelartheartbw}[1][colors=mono, tikz={scale={\f@size/300}, baseline=.1em}, stack]{% + \pixelart[#1]{ + ..11..11.. + .11111111. + 1111111111 + 1111111111 + 1111111111 + .11111111. + ..111111.. + ...1111... + ....11.... + }% +} + +\newcommand{\pixelartnamebw}[1][colors=mono, stack]{% + \begin{tikzpicture}[scale={\f@size/400}] + \draw (28, 0) node[opacity=0, anchor=south, inner sep=0pt]{\texttt{PixelArt}}; + \tikzpixelart[#1]{(0, 0)}{ + 111111...11...................111.....1...............1... + .11..11..11....................11....111.............11... + .11..11........................11...11.11............11... + .11..11.111..11....11..11111...11..11...11.11.111..111111. + .11111...11...11..11..11...11..11..11...11..111.11...11... + .11......11....1111...1111111..11..1111111..11..11...11... + .11......11.....11....11.......11..11...11..11.......11... + .11......11....1111...11.......11..11...11..11.......11... + .11......11...11..11..11...11..11..11...11..11.......11.11 + 1111....1111.11....11..11111..1111.11...11.1111.......111. + } + \end{tikzpicture}% +} + +\makeatother diff --git a/graphics/pgf/contrib/pixelart/pixelart.tex b/graphics/pgf/contrib/pixelart/pixelart.tex new file mode 100644 index 0000000000..1ab064ce56 --- /dev/null +++ b/graphics/pgf/contrib/pixelart/pixelart.tex @@ -0,0 +1,990 @@ +\documentclass[ + load-preamble-, + babel-options=english, + add-index=true, +]{cnltx-doc} + +\usepackage{pixelart} + +\setcnltx{ + name = pixelart, + title = \pixelartlogo, + version = v1.0.0, + date = 2022-11-16, + info = A \LaTeX{} package to draw pixel-art pictures , + authors = Louis Paternault , + email = spalax(at)gresille(dot)org , + url = https://framagit.org/spalax/pixelart , + abstract = {% + This package defines macros to draw pixel-art pictures using Lua\LaTeX{}. + } , + index-setup = { othercode=\footnotesize,level=\section}, + add-cmds = { + pixelart, + pixelartheart, + pixelartheartbw, + pixelartlogo, + pixelartlogobw, + pixelartname, + pixelartnamebw, + newpixelartcolors, + renewpixelartcolors, + setpixelartdefault, + setpixelartdebugon, + setpixelartdebugoff, + tikzpixelart, + }, + add-frame-options = { + innerleftmargin=2em + } +} + +\usepackage{booktabs} +\usepackage{csquotes} +\usepackage{graphicx} +\usepackage{markdown} +\usepackage{multicol} +\usepackage[autolanguage]{numprint} +\usepackage{siunitx} +\usepackage{subfigure} +\usepackage[inline]{enumitem} + +\begin{document} + +\part{Introduction} + +Installation instruction are given in section \ref{sec:install}. +Documentation about how to use this package (and examples) is given in part \ref{part:usage}. Most of the examples has been gathered in appendix \ref{sec:examples}. + +\section{Note to non-Lua\LaTeX{} users} + +Unfortunately, package \pkg{pixelart} does not works with \LaTeX{} or Xe\LaTeX. If you cannot or don't want to use Lua\LaTeX{}, you can: +\begin{itemize} + \item use the previous, unmaintained version of \pkg{pixelart}, named \pkg{pixelart0}, and included with this package; + \item or, better, use \pkg{pxpic}. +\end{itemize} + +\section{License} + +This work may be distributed and/or modified under the conditions of the \LPPL, either version 1.3 of this license or (at your option) any later version. + +\section{Installation} +\label{sec:install} + +\subsection{\textsc{Gnu}/Linux Distribution} + +If applicable, the easiest way to get \pkg{pixelart} working is by installing it by your distribution package. In Debian (and Ubuntu, and surely other distributions that inherit from Debian) it is packaged in \texttt{texlive-pictures} since version \texttt{2017.20180103-1}. So you can install it by running: + +\begin{lstlisting}[language=sh] +sudo apt install texlive-pictures +\end{lstlisting} + +\subsection{LaTeX distribution} + +This package is included both in \TeX{}Live and MiK\TeX{}. It can be installed using their respective package managers. + +\subsection{Manual installation} + +\begin{itemize} +\item Download the lastest archive : +\begin{description} +\item[Stable version] \url{https://mirrors.ctan.org/graphics/pgf/contrib/pixelart.zip} +\item[Development version] \url{https://framagit.org/spalax/pixelart/repository/archive.zip?ref=main} +\end{description} +\item Unzip the archive. +\item Move files \texttt{pixelart.sty} and \texttt{pixelart.lua} into a \LaTeX{} path. +\end{itemize} + +\part{Usage} +\label{part:usage} + +\section{Package options} + +The package accepts a single option. + +\begin{options} + \opt{draft} Loading the package with this options is equivalent to using option \option{draft} on every single call of command \cs{pixelart} (or \cs{tikzpixelart}). If your document contains a lot of those commands, using this option can speed up compilation. + For instance, on my outdated computer, compilation of this document takes about 11 seconds with this option, and more than 16 seconds without. + + See option \option*{draft} (page \pageref{option:draft}) for more information. +\end{options} + + +\section{Drawing pictures} + + \begin{figure} + \begin{sidebyside} + I \pixelart[ + tikz={ + red, + scale=.05, + baseline=.3em, + } + ]{ + ..11..11.. + .11111111. + 1111111111 + 1111111111 + 1111111111 + .11111111. + ..111111.. + ...1111... + ....11.... + } \LaTeX + \end{sidebyside} + \caption{Basic example} + \label{fig:basic} +\end{figure} + +\begin{commands} + \command{pixelart}[\oarg{options}{\marg{pixels}}] + This is the basic command to draw pixel-art. Its mandatory argument is a sequence of pixels, as characters which will be turned into colored squares (using a \env*{tikzpicture}, from Till Tantau's \pkg{TikZ}). Its basic usage is given in figure \ref{fig:basic} (page \pageref{fig:basic}). + + In argument \marg{pixels}, dots \texttt{.} are converted to transparent pixels, spaces and line breaks delimit pixel rows, and any character defines a color, depending on option \option{colors}. + + More information is given in section \ref{sec:pixels}. + + \begin{options} + \opt{pixels} The art, as a list of pixels. See section \ref{sec:pixels}. + + \keyval{colors}{options} Pixel colors. See section \ref{sec:colors}. + + \keybool{draft}\label{option:draft} Disable rendering of \cs{pixelart} and \cs{tikzpixelart} commands: on documents containing a lot of thoses commands, this can speed up compilation. The pixel art is replaced by a dummy drawing, which takes the same space as the pixel art it replaces. + + This option can be applied to every single \cs{pixelart} or \cs{tikzpixelart} of the document by using \verb+\usepackage[draft]{pixelart}+. + + See an example in \ref{example:draft}. + + \keyval-{margin}{length} Pixel-art pictures are \emph{enclosed} inside a \pkg*{tikz} \cs*{clip} command. Most of the time, you won't notice it, but when playing with options \option{style} or \option{tikz}, your picture might extend outside usual borders, and part of it might be clipped out. Use the \option*{margin} option to extend the clip area. See example \ref{example:margin}. + + \opt{squares} If set, each pixel is drawn using a separate \cs*{fill} command (more in section \ref{sec:squares}). This option is incompatible with \option{stack} (see section \ref{sec:squaresstack}). + + \opt{stack} If set, \pkg*{pixelart} will try to draw several adjacent pixels of the same color using a single \cs*{fill} command (more in section \ref{sec:stack}). This option is incompatible with \option{squares} (see section \ref{sec:squaresstack}). + + \keyval-{style}{keyword}\Default{pixelart}\label{option:style} Pixels are drawn using \cs*{fill} commands in a \env*{tikzpicture} environment. Those \cs*{fill} commands are applied the \texttt{pixelart} style by default (as in: \verb+\fill[pixelart] (0, 0) rectangle (1, 1);+). You can set another style by using this command. See an example in \ref{example:style}. + + \keyval{tikz}{options}\label{option:tikz} A pixel art is a bunch of \cs*{fill} commands in a \env*{tikzpicture}. Arguments to this option are passed as-is as optional arguments to the \env*{tikzpicture} environment. See examples in \ref{example:tikz}. + + You will probably use this option to make the pixel art smaller (it is, by default, probably bigger than what you want), and to change the baseline. See figure \ref{fig:basic} for an example. + + Note that a \cs*{clip} command, which does not accept arguments, is used to delimit the picture. So you might get an error if your \option*{tikz} option applies to \cs*{clip} commands (for instance, by using \texttt{every path/.style={bla bla bla}}, which would apply to the \cs*{clip} command, and would raise an error). In such cases, you might want to use option \option{style} instead (see page \pageref{option:style}). + + \end{options} + + \command{tikzpixelart}[\oarg{options}\marg{coord}\marg{pixels}] + Use this command if you want to draw pixel art pictures \emph{inside} a \env*{tikzpicture} environment. + + The \oarg{options} and \marg{pixels} arguments have the same meaning as the corresponding arguments to the \cs{pixelart} command (excepted for \option{tikz}, which is passed as is as the argument of a \env*{scope} environment). + The \marg{coord} is the coordinate of the bottom left corner of the pixel art. It is passed as is in a \pkg*{TikZ} \env*{scope} environment (\verb+\begin{scope}[shift={}]+), so you can use anything that will be correctly parsed by \pkg*{TikZ}. + + See examples in section \ref{example:tikzpixelart}. +\end{commands} + +\subsection{Pixels} +\label{sec:pixels} + +Pixels are defined as blocks of characters. Dots always represent transparent pixels, and spaces and line breaks always separate pixel rows. Then, other caracters encode different colors, depending on option \option{colors}. + +Let us analyse the following example. + +\begin{sidebyside} + \pixelart[ + colors=RGB, tikz={scale=.4} + ]{ + {yellow}GB + G.R + BR{} + } +\end{sidebyside} + +\begin{itemize} + \item The first row \texttt{\{yellow\}GB} means: one yellow pixel, one green pixel, one blue pixel. + \item The second row \texttt{G.R} means: one green pixel, one transparent pixel, one red pixel. + \item The last row \texttt{BR\{\}} means: one blue pixel, one red pixel, one pixel using the default \pkg*{TikZ} color (that is, a \cs*{fill} command is used to draw this pixel, without any \option*{color} option, which means the default \pkg*{TikZ} color is used; see option \option{tikz}, page \ref{option:tikz}). +\end{itemize} + +Note that: +\begin{itemize} + \item Line breaks and consecutive spaces are considered as a \emph{single} row separation. That is, the previous example could also have been written as \texttt{\{yellow\}B G.R\hspace{1cm}BR\{\}}. + \item New paragraph are not allowed inside a \marg{pixels} argument. + \item If rows do not have the same lenght (the same number of pixels), transparent pixels are added at the end of the small rows. +\end{itemize} + +Examples for the previous corner cases are given in section \ref{sec:corner}. + +Most of commands are expanded \emph{before} being passed as an argument to \cs*{pixelart}, so it is possible to use commands inside a \cs*{pixelart}\marg{pixels} argument. See section \ref{sec:commands} for an example. + +\subsection{Colors} +\label{sec:colors} + +In a \cs{pixelart} command, pixel colors can be defined explicitely, or using keys/values. + +\begin{description} + \item[Explicit] Any text surrounded by braces is transmitted as-is to the underlying \env*{tikzpicture}. That way, you can use anything you would use with \pkg*{TikZ} (which itself uses \pkg{xcolor}): \texttt{red}, \texttt{red!20}, \texttt{red!20!purple}, any user-defined color, or \texttt{\{\}}, which does not give any \option*{color} argument to the \cs*{fill} command used to draw this pixel, thus using default \pkg*{TikZ} color (see option \option{tikz}, page \pageref{option:tikz}). + \item[Key/Value] Any alphanumeric character (\texttt{a} to \texttt{z}, \texttt{A} to \texttt{Z}, \texttt{0} to \texttt{9}) not surrounded by braces is a key, which encodes the corresponding color defined in the \option{colors} argument. For instance, if \option{colors} is given as \texttt{colors=\{R=\{red\},G=\{green\}\}}, then, having \texttt{RG} in the \marg{pixels} argument is equivalent to \texttt{\{red\}\{green\}}. + + Using non-alphanumeric characters as keys of \option{colors} is not supported: it might work, but it is an undefined behaviour. + \end{description} + + The following examples illustrates this option. + + \begin{itemize} + \item Key/values: + \begin{sidebyside} + \pixelart[ + colors={R=red, G=green, B=blue} + ]{ + RG + GB + } + \end{sidebyside} + \item Explicit: + \begin{sidebyside} + \pixelart{ + {cyan}{magenta} + {yellow}{black} + } + \end{sidebyside} + \item Mix: + \begin{sidebyside} + \pixelart[ + colors={R=red, G=green, B=blue} + ]{ + RG + {yellow}B + } + \end{sidebyside} + \end{itemize} + + If you use the same setting several times, you can define it once for all using \cs{newpixelartcolors}. + +\begin{commands} + \command{newpixelartcolors}[\marg{name}\marg{key/value}] + Once a color set has been defined, to use it, simply use its name as an argument to \option{colors} instead of the whole keys/values. See an example in \ref{example:newpixelartcolors}. + \begin{options} + \opt*{name} Name of your color set. + \opt*{key/value} Your color set, as keys/values. + \end{options} + \command{renewpixelartcolors}[\marg{name}\marg{key/value}] + The previous command will fail if a color set \marg{name} is already defined. This command will always succeed, whether a color set \marg{name} already exists or not. +\end{commands} + +The following key/value settings are predefined (examples are given in \ref{example:predefinedcolors}). + +\begin{description} + \item[\texttt{explicit} :] No keys/values: pixel colors have to be explicitely defined. + \begin{sourcecode} + \newpixelartcolors{explicit}{} + \end{sourcecode} + + \item[\texttt{RGB} :] Define the primary colors red, green, blue, as well as black and white. + \begin{sourcecode} + \newpixelartcolors{RGB}{ + R=red, + G=green, + B=blue, + W=white, + K=black + } + \end{sourcecode} + + \item[\texttt{BW} :] Black and white. + \begin{sourcecode} + \newpixelartcolors{BW}{ + 0=white, + 1=black, + } + \end{sourcecode} + + \item[\texttt{gray} :] Gray scale: \texttt{0} is white, \texttt{9} is black, and digits \texttt{0} to \texttt{9} are a gray scale from white to black. + \begin{sourcecode} + \newpixelartcolors{gray}{ + 0=white, + 1=white!89!black, + 2=white!78!black, + 3=white!67!black, + 4=white!56!black, + 5=white!44!black, + 6=white!33!black, + 7=white!22!black, + 8=white!11!black, + 9=black, + } + \end{sourcecode} + + \item[\texttt{mono} :] Monochromatic: any character encodes the default TikZ color (black by default, may be changed with options \option{tikz} or \option{style}). + \begin{sourcecode} + \newpixelartcolors{mono}{ + a={}, + b={}, + c={}, + % ... + 9={}, + } + \end{sourcecode} +\end{description} + +\subsection{More about option \option*{squares}} +\label{sec:squares} + +When using \option{squares}, each pixel is a separate colored square. Thus, artifacts can appear when viewing the document, as illustrated in figure \ref{fig:artifact}. + +\begin{figure} + \centering + \includegraphics{artifacts} + \caption{Artifacts appearing with option \option*{squares} : the white lines should not exist.} + \label{fig:artifact} +\end{figure} + +To remove those artifacts, you can +\begin{enumerate*}[label={(\arabic*)}] + \item use option \option{stack} instead (see section \ref{sec:stack}), or + \item use option \option{overlap}. +\end{enumerate*} + +\begin{options} + \keyval-{overlap}{number} Assuming the square width is 1, \marg{number} is the size of the overlap: how much a square overlaps over the next one. With a positive number, the artifact (white line between two pixels) will disappear as the adjacent pixels are merged. + + Note that using a negative value to \option{overlap} is also allowed, and will separate each pixel from its neighbour, giving a the look of a LCD screen. + + See examples in section \ref{example:overlap}. +\end{options} + +\subsection{More about option \option*{stack}} +\label{sec:stack} + +If option \option{stack} is set, \pkg*{pixelart} tries to merge adjacent pixels of the same color, to draw them at once. Thus, it mostly remove the artifacts problem discussed with option \option*{squares} (although it may still occur). + +Example in section \ref{example:stacksteps} shows how different color shapes are stacked onto each other to produce the pixel art. + +\subsection{Which option: \option*{squares} or \option*{stack}?} +\label{sec:squaresstack} + +Which option should you use: \option*{squares} or \option*{stack}? + +To compare the different algorithms, three files have been compiled, each with one big pixel art command (see example \ref{example:benchmark}), with three different algorithms: outdated package \pkg*{pixelart0}, and options \option*{stack} and \option*{squares} of \pkg*{pixelart}. The result can be seen in figure \ref{fig:benchmark} (page \pageref{fig:benchmark}). + +Unless you want to use option \option{overlap} of option \option{squares} (see section \ref{sec:squares}), you probably want to use option \option*{stack}: +\begin{itemize} + \item it is faster (see benchmark); + \item it produces smaller files (see benchmark); + \item it mostly remove artifacts. +\end{itemize} + +Thus, the \option{stack} option is the default one used by \pkg*{pixelart}. + +\begin{figure} + \centering + + \subtable[File size (\si{kB})]{ + \begin{tabular}{r*{3}{n{3}{1}}} + \toprule + &\multicolumn{3}{c}{Drawing}\\ + & {mono} & {concentric} & {checker} \\ + \midrule + \pkg*{pixelart0} & 243 & & \\ + \pkg*{pixelart} \option*{stack} & 2.9 & 4.4 & 158 \\ + \pkg*{pixelart} \option*{squares} & 245 & 263 & 252 \\ + \bottomrule + \end{tabular} + } + \subtable[Compilation time (seconds)]{ + \begin{tabular}{r*{3}{n{3}{1}}} + \toprule + &\multicolumn{3}{c}{Drawing}\\ + & {mono} & {concentric} & {checker} \\ + \midrule + \pkg*{pixelart0} & 38.7 & & \\ + \pkg*{pixelart} \option*{stack} & 1.0 & 1.0 & 24.4 \\ + \pkg*{pixelart} \option*{squares} & 19.9 & 28.3 & 27.1 \\ + \bottomrule + \end{tabular} + } + \caption{Benchmark : \pkg*{pixelart0} vs. \option*{stack} vs \option*{squares}} + \label{fig:benchmark} +\end{figure} + +\section{Default options} + +You can use the following command to define options once for all. + +\begin{commands} + \command{setpixelartdefault}[\marg{options}] Any options defined here will affect later \cs*{pixelart} or \cs*{tikzpixelart} commands, unless those options are explicitely set. + + See example in section \ref{example:default}. +\end{commands} + +\section{Logos} + +If you want to credit \pkg*{pixelart} in a fancy way, you can use one of those logos. Apart from being gorgeous, they include a transparent text (so that they are searchable and copyable) and they scale with the current font size. + +\begin{multicols}{2} +\begin{commands} + \command{pixelartlogo} + \pixelartlogo{} + Name and heart, in color. + + \command{pixelartheart} + \pixelartheart{} + Heart only, in color. + + \command{pixelartname} + \pixelartname{} + Name only, in color. + + \command{pixelartlogobw} + \pixelartlogobw{} + Name and heart, black and white. + + \command{pixelartheartbw} + \pixelartheartbw{} + Heart only, black and white + + \command{pixelartnamebw} + \pixelartnamebw{} + Name only, black and white. +\end{commands} +\end{multicols} + +\section{Debugging} + +What if drawing your pixel art throws an error? + +\begin{enumerate} + \item Standard output prints one \texttt{\% pixelart 2, file ./foo.tex, input line 19} per \cs*{pixelart} or \cs*{tikzpixelart} command. If compilation failed right after this line, look at the given file: the \cs*{pixelart} command might be wrong. + \item If you do not see the problem, set debug mode on. + + \begin{multicols}{2} + \begin{commands} + \command{setpixelartdebugon} Set debug on. + \command{setpixelartdebugoff} Set debug off. + \end{commands} + \end{multicols} + + Using those commands, the following piece of information will be logged: + + \begin{itemize} + \item the parsed options of \cs*{pixelart} and \cs*{tikzpixelart}; + \item the \marg{pixels} argument of those commands; + \item the \pkg*{tikz} commands used to draw the picture; + \item and maybe some other stuff I forgot. + \end{itemize} + + Note that you can have as many \cs*{setpixelartdebugon} and \cs*{setpixelartdebugoff} commands as you want, even if debug is already on or off. + + A good idea is to copy the \pkg*{tikz} commands that are logged (those are the commands used to draw the pixel art), and paste them in a new file. Try to compile it. Are some of your arguments at fault? Bad value for the \option{tikz} option can produce faulty \pkg*{tikz} code. + \item Still no idea why your \cs*{pixelart} command fails? Seek help on your usual places, or report a bug. +\end{enumerate} + +\appendix +\part{Appendix} + +\section{Examples} +\label{sec:examples} + +\subsection{Corner cases of \cs*{pixelart}\marg{pixels} argument} +\label{sec:corner} + +\setpixelartdefault{tikz={scale=.3}} +\begin{itemize} + \item Line breaks and multiple spaces are considered as a \emph{single} row separation. +\begin{sidebyside} + \pixelart{ + 1.1 + .1. + 1.1 + } + \pixelart{ + 1.1 .1. + 1.1 + } +\end{sidebyside} +\item Multiple line breaks (new paragraphs) are not supported: at best, they do not give the expected result; at worst, compilation will fail. +\begin{sidebyside} + \pixelart{ + .1 + 1. + } + \pixelart{ + .1 + + 1. + } +\end{sidebyside} +\item Empty pixels are automatically added at the end of shorter lines. + \begin{sidebyside} + \pixelart{ + 1 + .1 + 1.1 + } + \pixelart{ + 1.. + .1. + 1.1 + } + \end{sidebyside} +\end{itemize} + +\subsection{Commands inside \cs*{pixelart}\marg{pixels} argument} +\label{sec:commands} + +If we are too lazy to repeat every single pixel to draw a checker board, we can use commands. + +\setpixelartdefault{tikz={scale=.2}} +\begin{enumerate}[label={Example \arabic*:}] + \item Each couple of lines is repetead four times. + + \begin{sidebyside} + \newcommand{\twolines}{ + .1.1.1.1 1.1.1.1.% + } + \pixelart{ + \twolines + \twolines + \twolines + \twolines + } + \end{sidebyside} + + \item \cs*{foreach} outside \cs*{pixelart} + + \begin{sidebyside} + \gdef\board{} + \gdef\line{1} + \foreach \j in {1, ..., 3}{ + \xdef\line{\line.1} + } + \foreach \i in {1, ..., 4}{ + \xdef\board{% + \board + \line. + .\line. + } + } + \pixelart{\board} + \end{sidebyside} + + \item I do not understand \LaTeX{} enough to explain why, however, \cs*{foreach} inside a \cs*{pixelart} does not work. + + \begin{example}[code-only=true] + \pixelart{ + \foreach \i in {1, ..., 8}{ + 1\foreach \j in {1, ..., 3}{.1}. + \foreach \j in {1, ..., 3}{.1}.1 + } + } + \end{example} +\end{enumerate} + +\subsection{Define new color sets: \cs*{newpixelartcolors}} +\label{example:newpixelartcolors} + +\setpixelartdefault{tikz={scale=.3}} +\begin{itemize} + \item Colors may be defined in the \option{colors} option + \begin{example} + \definecolor{purple1}{RGB}{247, 176, 207} + \definecolor{purple2}{RGB}{238, 33, 120} + \definecolor{purple3}{RGB}{214, 45, 117} + \definecolor{purple4}{RGB}{217, 25, 92} + \definecolor{purple5}{RGB}{173, 29, 69} + \pixelart[colors={ + 1=purple1, 2=purple2, 3=purple3, 4=purple4, 5=purple5, + }]{ + .54.43. + 4224215 + 3445435 + .52424. + ..434.. + ...2... + } + \end{example} + +\item Colors may be defined using \cs{newpixelartcolors} + \begin{example} + \definecolor{purple1}{RGB}{247, 176, 207} + \definecolor{purple2}{RGB}{238, 33, 120} + \definecolor{purple3}{RGB}{214, 45, 117} + \definecolor{purple4}{RGB}{217, 25, 92} + \definecolor{purple5}{RGB}{173, 29, 69} + \newpixelartcolors{purple}{ + 1=purple1, 2=purple2, 3=purple3, 4=purple4, 5=purple5, + } + \pixelart[colors=purple]{ + .54.43. + 4224215 + 3445435 + .52424. + ..434.. + ...2... + } + \end{example} +\end{itemize} + +\subsection{Predefined color sets} +\label{example:predefinedcolors} + +\begin{description} + \item[mono]~ + \begin{sidebyside} + \pixelart[colors=mono, tikz={red, scale=.3}]{ + ..01..23.. + .456789ab. + cdefghijkl + mnopqrstuv + wxyzABCDEF + .GHIJKLMN. + ..OPQRST.. + ...UVWX... + ....YZ.... + } + \end{sidebyside} + \item[gray]~ + \begin{sidebyside} + \pixelart[colors=gray, tikz={scale=.3}]{ + 987654 + 876543 + 765432 + 654321 + 543210 + 43210. + } + \end{sidebyside} + \item[BW]~ + \begin{sidebyside} + \pixelart[colors=BW, tikz={scale=.3}]{ + 01010101 + 10101010 + 01010101 + 10101010 + 01010101 + 10101010 + 01010101 + 10101010 + } + \end{sidebyside} + \item[RGB]~ + \begin{sidebyside} + \pixelart[colors=RGB, tikz={scale=.1}]{ + .....................KKKKKKK + .RRR...GG..BBB..K..K.KWKKKWK + .R..R.G..G.B..B.K.K..KWKKKWK + .RRR..G....BBB..KK...KWKKKWK + .R.R..G.GG.B..B.K.K..KWKWKWK + .R..R.G..G.B..B.K..K.KWKWKWK + .R..R..GG..BBB..K..K.KKWKWKK + .....................KKKKKKK + } + \end{sidebyside} +\end{description} + +\subsection{Option \option*{draft}} +\label{example:draft} + +\begin{sidebyside} + \setpixelartdefault{tikz={scale=.3}} + \pixelart[colors=RGB]{ + ..RR..RR.. + .RRRRRRRR. + RRRRRRRRRR + RRRRRRRRRR + RRRRRRRRRR + .RRRRRRRR. + ..RRRRRR.. + ...RRRR... + ....RR.... + } + + \pixelart[colors=RGB, draft]{ + ..RR..RR.. + .RRRRRRRR. + RRRRRRRRRR + RRRRRRRRRR + RRRRRRRRRR + .RRRRRRRR. + ..RRRRRR.. + ...RRRR... + ....RR.... + } +\end{sidebyside} + +\subsection{Option \option*{style}} +\label{example:style} + +\setpixelartdefault{colors=mono} + +\begin{sidebyside} + \pixelart{ + .1 + 1. + } +\end{sidebyside} + +\begin{sidebyside} + \pixelart[tikz={pixelart/.style={red}}]{ + .1 + 1. + } +\end{sidebyside} + +\begin{sidebyside} + \tikzset{pixelart/.style={blue, draw=orange, very thick, rounded corners=5}} + \pixelart{ + .1 + 1. + } +\end{sidebyside} + +\begin{sidebyside} + \pixelart[tikz={pixelart/.style={green}}]{ + .1 + 1. + } +\end{sidebyside} + +\begin{sidebyside} + \tikzset{myfancystyle/.style={yellow}} + \pixelart[style=myfancystyle]{ + .1 + 1. + } +\end{sidebyside} + +A more complex example. + +\begin{sidebyside} + \tikzset{pixelart/.style={cyan, very thick, draw=black, rounded corners=5}} + \pixelart[squares={overlap=-.2}, colors=mono, tikz={scale=.5}, margin=.1]{ + 1..1.1..1 + 1..1....1 + 1111.1..1 + 1..1.1... + 1..1.1..1 + } +\end{sidebyside} + +\subsection{Option \option*{tikz}} +\label{example:tikz} + +\begin{sidebyside} + \pixelart[stack, colors={Y=yellow, K=black}, tikz={scale=.5, rounded corners=5}]{ + ..YYYY.. + .YYYYYY. + YYKYYKYY + YYYYYYYY + YKYYYYKY + YYKKKKYY + .YYYYYY. + ..YYYY.. + } +\end{sidebyside} + +\subsection{Drawing steps with the \option*{stack} option} +\label{example:stacksteps} + +Here is how an image is built with the \option{stack} option: each of the following steps is a \cs*{fill} command with carefully crafted shape. Those filled area are \enquote{stacked} on each other, to produce the expected result. + +Line per line, the algorithm checks if the pixels have been drawn yet. In the following steps, the gray cross marks the first pixel that was not drawn yet, that triggered a new \cs*{fill} command. + +\centering +%\pixelart[stack, colors=RGB]{ +% BBBBBBBBBBBBB +% BRRRBRRRBRRRB +% BRBRBRBRBRBBB +% BRRRBRRRBRBBB +% BRBRBRBRBRBBB +% BRBRBRRRBRRRB +% BBBBBBBBBBBBB +%} +\begin{tabular}{*{3}{c}} + \begin{tikzpicture}[scale=0.3] + \fill[color=blue] (1, 1) -- (1, 8) -- (14, 8) -- (14, 1) -- cycle ; + \draw[very thick, gray] (1.1, 1.1) -- (1.9, 1.9) (1.1, 1.9) -- (1.9, 1.1); + \end{tikzpicture}& + \begin{tikzpicture}[scale=0.3] + \fill[color=blue] (1, 1) -- (1, 8) -- (14, 8) -- (14, 1) -- cycle ; + \fill[color=red] (2, 2) -- (2, 7) -- (5, 7) -- (5, 2) -- (4, 2) -- (4, 4) -- (3, 4) -- (3, 2) -- cycle ; + \draw[very thick, gray] (2.1, 2.1) -- (2.9, 2.9) (2.1, 2.9) -- (2.9, 2.1); + \end{tikzpicture}& + \begin{tikzpicture}[scale=0.3] + \fill[color=blue] (1, 1) -- (1, 8) -- (14, 8) -- (14, 1) -- cycle ; + \fill[color=red] (2, 2) -- (2, 7) -- (5, 7) -- (5, 2) -- (4, 2) -- (4, 4) -- (3, 4) -- (3, 2) -- cycle ; + \fill[color=red] (6, 2) -- (6, 7) -- (9, 7) -- (9, 2) -- cycle ; + \draw[very thick, gray] (6.1, 2.1) -- (6.9, 2.9) (6.1, 2.9) -- (6.9, 2.1); + \end{tikzpicture}\\ + Step 1&Step 2&Step 3\\ + \midrule + \begin{tikzpicture}[scale=0.3] + \fill[color=blue] (1, 1) -- (1, 8) -- (14, 8) -- (14, 1) -- cycle ; + \fill[color=red] (2, 2) -- (2, 7) -- (5, 7) -- (5, 2) -- (4, 2) -- (4, 4) -- (3, 4) -- (3, 2) -- cycle ; + \fill[color=red] (6, 2) -- (6, 7) -- (9, 7) -- (9, 2) -- cycle ; + \fill[color=red] (10, 2) -- (10, 7) -- (13, 7) -- (13, 6) -- (11, 6) -- (11, 3) -- (13, 3) -- (13, 2) -- cycle ; + \draw[very thick, gray] (10.1, 2.1) -- (10.9, 2.9) (10.1, 2.9) -- (10.9, 2.1); + \end{tikzpicture}& + \begin{tikzpicture}[scale=0.3] + \fill[color=blue] (1, 1) -- (1, 8) -- (14, 8) -- (14, 1) -- cycle ; + \fill[color=red] (2, 2) -- (2, 7) -- (5, 7) -- (5, 2) -- (4, 2) -- (4, 4) -- (3, 4) -- (3, 2) -- cycle ; + \fill[color=red] (6, 2) -- (6, 7) -- (9, 7) -- (9, 2) -- cycle ; + \fill[color=red] (10, 2) -- (10, 7) -- (13, 7) -- (13, 6) -- (11, 6) -- (11, 3) -- (13, 3) -- (13, 2) -- cycle ; + \fill[color=blue] (7, 3) -- (7, 4) -- (8, 4) -- (8, 3) -- cycle ; + \draw[very thick, gray] (7.1, 3.1) -- (7.9, 3.9) (7.1, 3.9) -- (7.9, 3.1); + \end{tikzpicture}& + \begin{tikzpicture}[scale=0.3] + \fill[color=blue] (1, 1) -- (1, 8) -- (14, 8) -- (14, 1) -- cycle ; + \fill[color=red] (2, 2) -- (2, 7) -- (5, 7) -- (5, 2) -- (4, 2) -- (4, 4) -- (3, 4) -- (3, 2) -- cycle ; + \fill[color=red] (6, 2) -- (6, 7) -- (9, 7) -- (9, 2) -- cycle ; + \fill[color=red] (10, 2) -- (10, 7) -- (13, 7) -- (13, 6) -- (11, 6) -- (11, 3) -- (13, 3) -- (13, 2) -- cycle ; + \fill[color=blue] (7, 3) -- (7, 4) -- (8, 4) -- (8, 3) -- cycle ; + \fill[color=blue] (3, 5) -- (3, 6) -- (4, 6) -- (4, 5) -- cycle ; + \draw[very thick, gray] (3.1, 5.1) -- (3.9, 5.9) (3.1, 5.9) -- (3.9, 5.1); + \end{tikzpicture}\\ + Step 4&Step 5&Step 6\\ + \begin{tikzpicture}[scale=0.3] + \fill[color=blue] (1, 1) -- (1, 8) -- (14, 8) -- (14, 1) -- cycle ; + \fill[color=red] (2, 2) -- (2, 7) -- (5, 7) -- (5, 2) -- (4, 2) -- (4, 4) -- (3, 4) -- (3, 2) -- cycle ; + \fill[color=red] (6, 2) -- (6, 7) -- (9, 7) -- (9, 2) -- cycle ; + \fill[color=red] (10, 2) -- (10, 7) -- (13, 7) -- (13, 6) -- (11, 6) -- (11, 3) -- (13, 3) -- (13, 2) -- cycle ; + \fill[color=blue] (7, 3) -- (7, 4) -- (8, 4) -- (8, 3) -- cycle ; + \fill[color=blue] (3, 5) -- (3, 6) -- (4, 6) -- (4, 5) -- cycle ; + \fill[color=blue] (7, 5) -- (7, 6) -- (8, 6) -- (8, 5) -- cycle ; + \draw[very thick, gray] (7.1, 5.1) -- (7.9, 5.9) (7.1, 5.9) -- (7.9, 5.1); + \end{tikzpicture}\\ + Step 7\\ + \bottomrule +\end{tabular} + +\subsection{Option \option*{overlap}} +\label{example:overlap} + +\begin{sidebyside} + \setpixelartdefault{tikz={scale=.3}} + \newcommand{\three}{ + .111. + 11.11 + ...11 + ...11 + ..11. + ...11 + ...11 + 11.11 + .111. + } + \pixelart[squares={overlap=.1}]{ + \three + } + \pixelart[squares={overlap=0}]{ + \three + } + \pixelart[squares={overlap=-.1}]{ + \three + } +\end{sidebyside} + +\subsection{Command \cs*{tikzpixelart}} +\label{example:tikzpixelart} + +\begin{sidebyside} + \begin{tikzpicture} + \fill[red] (0, 0) circle (1); + \tikzpixelart[tikz={color=green}]{(-1, -1)}{ + 1 + .1 + 1.1 + } + \end{tikzpicture} +\end{sidebyside} + +\subsection{Pictures used for the benchmark} +\label{example:benchmark} + +The benchmark discussed in section \ref{sec:squaresstack} (page \pageref{sec:squaresstack}) uses three files with three big \cs*{pixelart} commands. A small version of those commands is shown below. + +\setpixelartdefault{colors=RGB, tikz={scale=.3}} +\begin{description} + \item[mono] Every single pixel of the same color. + \begin{sidebyside} + \pixelart{ + KKKKKKKK + KKKKKKKK + KKKKKKKK + KKKKKKKK + KKKKKKKK + KKKKKKKK + KKKKKKKK + KKKKKKKK + } + \end{sidebyside} + + \item[concentric] Cencentric squares, that is, several area with adjacent pixels of the same color. + \begin{sidebyside} + \pixelart{ + GGGGGGGG + GKKKKKKG + GKGGGGKG + GKGRRGKG + GKGRRGKG + GKGGGGKG + GKKKKKKG + GGGGGGGG + } + \end{sidebyside} + + \item[checker] A (kind of) checker board, where no two adjacent pixels have the same color. + \begin{sidebyside} + \pixelart{ + RGRGRGRG + BKBKBKBK + RGRGRGRG + BKBKBKBK + RGRGRGRG + BKBKBKBK + RGRGRGRG + BKBKBKBK + } + \end{sidebyside} +\end{description} + +\subsection{Default options} +\label{example:default} + +\begin{sidebyside} + \setpixelartdefault{colors=mono, tikz={scale=.2, red}} + + From now on, pixel art pictures will be small, and red: + \pixelart{1. .1}. + + Excepted this one: + \pixelart[ + tikz={scale=.4, blue} + ]{1. .1}. + + Back to normal: + \pixelart{1. .1}. +\end{sidebyside} + +\subsection{Option \option*{margin}} +\label{example:margin} + +In the first picture, you can see that part of the orange line has been clipped away. In the second one, with option \option{margin} correctly set, it is not clipped away. + +\begin{sidebyside} + \setpixelartdefault{squares} + \tikzset{pixelart/.style={ + draw=orange, + rounded corners=5, + line width=5, + }} + + \pixelart{11 11} + + \pixelart[margin=.1]{11 11} +\end{sidebyside} + +\section{Change History} + +This is a raw copy of the \href{https://framagit.org/spalax/pixelart/-/blob/main/CHANGELOG.md}{\textsl{CHANGELOG.md}} file that can be found in the git repository of \pkg*{pixelart}. + +\markdownInput{CHANGELOG.md} + +\end{document} diff --git a/graphics/pgf/contrib/pixelart/pixelart0.pdf b/graphics/pgf/contrib/pixelart/pixelart0.pdf new file mode 100644 index 0000000000..ec118f46fb Binary files /dev/null and b/graphics/pgf/contrib/pixelart/pixelart0.pdf differ diff --git a/graphics/pgf/contrib/pixelart/pixelart0.sty b/graphics/pgf/contrib/pixelart/pixelart0.sty new file mode 100644 index 0000000000..dbf96cdc52 --- /dev/null +++ b/graphics/pgf/contrib/pixelart/pixelart0.sty @@ -0,0 +1,114 @@ +%% Copyright 2017-2022 Louis Paternault +%% +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +%% This work has the LPPL maintenance status `maintained'. +%% +%% The Current Maintainer of this work is Louis Paternault +%% +%% This work consists of the files pixelart0.sty and pixelart0.tex. + +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{pixelart0} + [2022/11/16 v0.3.0 A package to draw pixel-art pictures] + +\RequirePackage{pgf} +\RequirePackage{pgfopts} +\usepgfmodule{parser} +\RequirePackage{tikz} +\usetikzlibrary{calc} +\RequirePackage{pgfkeys} +\RequirePackage{etoolbox} + +\makeatletter + +\newif\ifpixelart@draft +\pgfkeys{ + /PIXELART/.cd, + draft/.is if=pixelart@draft, + draft=false, +} +\ProcessPgfPackageOptions{/PIXELART} +\pgfkeys{ + /PIXELART/BWPIXELART/.is family, + /PIXELART/BWPIXELART, + scale/.value required, + scale/.code={\pgfkeyssetvalue{/PIXELART/BWPIXELART/scale}{#1}}, + scale=1, + raise/.code={\pgfkeyssetvalue{/PIXELART/BWPIXELART/raise}{#1}}, + raise/.value required, + raise=0pt, + color/.value required, + color/.code={\pgfkeyssetvalue{/PIXELART/BWPIXELART/color}{#1}}, + color=black, +} + +\pgfkeys{ + /PIXELART/TIKZBWPIXELART/.is family, + /PIXELART/TIKZBWPIXELART, + scale/.value required, + scale/.code={\pgfkeyssetvalue{/PIXELART/TIKZBWPIXELART/scale}{#1}}, + scale=1, + color/.value required, + color/.code={\pgfkeyssetvalue{/PIXELART/TIKZBWPIXELART/color}{#1}}, + color=black, +} + +\pgfparserdef{@bwpixelart}{initial}{blank space \space}{ + \@bwpa@newline +} +\pgfparserdef{@bwpixelart}{initial}{the character 0}{ + \coordinate (@pixelart) at ($(@pixelart) + (1, 0)$); +} +\pgfparserdef{@bwpixelart}{initial}{the character 1}{ + \fill (@pixelart) rectangle ++(1, 1); + \coordinate (@pixelart) at ($(@pixelart) + (1, 0)$); +} +\pgfparserdef{@bwpixelart}{initial}{the letter @}{ + \pgfparserswitch{final} +} + +\newcommand{\@bwpa@newline}{ + \coordinate (@pixelart) at ($(@pixelart@startline) + (0, -1)$); + \coordinate (@pixelart@startline) at (@pixelart); +} + +\newcommand{\bwpixelart}[2][]{{% + \pgfkeys{/PIXELART/BWPIXELART, #1}% + \raisebox{\pgfkeysvalueof{/PIXELART/BWPIXELART/raise}}{% + \tikz[ + scale=\pgfkeysvalueof{/PIXELART/BWPIXELART/scale}, + ]{ + \tikzbwpixelart[% + color=\pgfkeysvalueof{/PIXELART/BWPIXELART/color}, + ]{(0, 0)}{#2} + }% + }% +}} + +\newcommand{\tikzbwpixelart}[3][]{ + \pgfkeys{/PIXELART/TIKZBWPIXELART, #1} + \ifpixelart@draft + % Draft mode. Nothing to parse, nothing to show! + \else + \begin{scope}[shift={#2}] + \begin{scope}[#1] + \coordinate (@pixelart) at (0, 1); + \coordinate (@pixelart@startline) at (@pixelart); + + \pgfparserparse{@bwpixelart} + #3 @ + \end{scope} + \end{scope} + \fi +} + +\makeatother + +\endinput diff --git a/graphics/pgf/contrib/pixelart/pixelart0.tex b/graphics/pgf/contrib/pixelart/pixelart0.tex new file mode 100644 index 0000000000..2c64add4e3 --- /dev/null +++ b/graphics/pgf/contrib/pixelart/pixelart0.tex @@ -0,0 +1,454 @@ +\documentclass{ltxdoc} + +\RecordChanges + +\usepackage{hyperref} +\usepackage{pixelart0} +\usepackage{numprint} +\usepackage{mdframed} + +\usepackage{listings} +\lstset{ + language=[LaTeX]TeX, + numbers=left, + numberstyle=\tiny, + backgroundcolor=\color{yellow!20}, + basicstyle=\small\color{black}\ttfamily, + keywordstyle=\color{blue!80}\sffamily, + commentstyle=\color{olive}, + stringstyle=\color{red}, +} + +\usepackage{textcomp} +\usepackage{fontspec} +\usepackage[english]{babel} + +\usepackage{manfnt} + +\begin{document} + +\CheckSum{0} +\CharacterTable + {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z + Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z + Digits \0\1\2\3\4\5\6\7\8\9 + Exclamation \! Double quote \" Hash (number) \# + Dollar \$ Percent \% Ampersand \& + Acute accent \' Left paren \( Right paren \) + Asterisk \* Plus \+ Comma \, + Minus \- Point \. Solidus \/ + Colon \: Semicolon \; Less than \< + Equals \= Greater than \> Question mark \? + Commercial at \@ Left bracket \[ Backslash \\ + Right bracket \] Circumflex \^ Underscore \_ + Grave accent \` Left brace \{ Vertical bar \| + Right brace \} Tilde \~} + +\GetFileInfo{pixelart0.dtx} + +\DoNotIndex{\#,\$,\%,\&,\@,\\,\{,\},\^,\_,\~,\ ,\!,\(,\),\,} +\DoNotIndex{\@bwpa@newline} +\DoNotIndex{\begin} +\DoNotIndex{\coordinate} +\DoNotIndex{\end, \else} +\DoNotIndex{\fill, \fi} +\DoNotIndex{\ifpixelart@draft} +\DoNotIndex{\makeatletter, \makeatother} +\DoNotIndex{\newcommand, \newif} +\DoNotIndex{\ProcessPgfPackageOptions, \pgfkeys, \pgfkeyssetvalue, \pgfkeysvalueof, \pgfparserdef, \pgfparserparse, \pgfparserswitch} +\DoNotIndex{\raisebox, \RequirePackage} +\DoNotIndex{\space} +\DoNotIndex{\tikz} +\DoNotIndex{\usepgfmodule, \usetikzlibrary} + +\title{ + \begin{tikzpicture} + \tikzbwpixelart[scale=.037]{(-1.05, .14)}{% + 111111000110000000000000000000111000001000000000000000100000011100 + 011001100110000000000000000000011000011100000000000001100000100010 + 011001100000000000000000000000011000110110000000000001100001100111 + 011001101110011000011001111100011001100011011011100111111001100111 + 011111000110001100110011000110011001100011001110110001100001101011 + 011000000110000111100011111110011001111111001100110001100001101011 + 011000000110000011000011000000011001100011001100000001100001110011 + 011000000110000111100011000000011001100011001100000001100001110011 + 011000000110001100110011000110011001100011001100000001101100100010 + 111100001111011000011001111100111101100011011110000000111000011100 + }% + \draw (0, 0) node[opacity=0]{\LARGE PixelArt0}; + \end{tikzpicture}\thanks{ + This document corresponds to \textsf{pixelart0}~0.3.0, dated 2022-11-16. + Home page, bug requests, etc. at \url{http://framagit.org/spalax/pixelart} + }\\A package to draw pixel-art pictures.} +\author{Louis Paternault\\ \texttt{spalax(at)gresille(dot)org}} + +\maketitle + +\begin{abstract} +This package defines macros to draw pixel-art pictures using \LaTeX{}. +\end{abstract} + +\changes{v0.3.0}{2022/10/23}{Rename \textsf{pixelart} to \textsf{pixelart0}.} +\begin{mdframed} +\textbf{\textdbend Warning :} This package is an outdated version of \textsf{pixelart}, that works with \LaTeX (while \textsf{pixelart} requires Lua\LaTeX). It is kept around for background compatibility. +\begin{itemize} + \item If you are a new user: + \begin{itemize} + \item if you are using Lua\LaTeX, you can use \textsf{pixelart} version 1.0.0 or later; + \item otherwise, you can use the \textsf{pxpic} package, by Jonathan P. Spratte. +\end{itemize} +\item if you did use \textsf{pixelart} before version 1.0.0, you are advised to switch to \textsf{pixelart} version 1.0.0 or later, or to switch to \textsf{pxpic} (see above). Or you can replace your \lstinline|\requirepackage{pixelart}| by \lstinline|\requirepackage{pixelart0}| to continue using this outdated version. +\end{itemize} +\end{mdframed} + +\setcounter{tocdepth}{2} +\tableofcontents + +\section{Introduction} +This document introduces the \textsf{pixelart0} package, used to draw pixel-art pictures. + +It is an outdated version of \textsf{pixelart} (before version 1.0.0), kept as part of \textsf{pixelart} for backward compatibility. + +\subsection{License} +This work may be distributed and/or modified under the +conditions of the \LaTeX Project Public License, either version 1.3 +of this license or (at your option) any later version. + +Further information can be found in the |.dtx| file used to build this +document. + +\subsection{Overview} +Installation instruction are given in section \ref{sec:install}. +Documentation about how to use this package (and examples) is given in section +\ref{sec:usage}. Section \ref{sec:bugs} lists some known bugs and +limitations. + +\section{Download and Install} +\label{sec:install} + +\subsection{\textsc{Gnu}/Linux Distribution} + +If applicable, the easiest way to get |pixelart0| working is by installing it by your distribution package. In Debian (and Ubuntu, and surely other distributions that inherit from Debian) it is packaged in |texlive-pictures| since version \texttt{2017.20180103-1}. So you can install it by running: + +\begin{quote} +|sudo apt install texlive-pictures| +\end{quote} + +\subsection{LaTeX distribution} + +This package is included both in \TeX{}Live and MiK\TeX{}, as part of \textsf{pixelart}. It can be installed using their respective package managers. + +\subsection{Manual installation} + +\begin{itemize} +\item Download the lastest archive : +\begin{description} +\item[Stable version] \url{https://mirrors.ctan.org/graphics/pgf/contrib/pixelart.zip} +\item[Development version] \url{https://framagit.org/spalax/pixelart/repository/archive.zip?ref=main} +\end{description} +\item Unzip the archive. +\item If you got the archive from CTAN (stable version), move file \texttt{tex/latex/pixelart/pixelart0.sty} in a \LaTeX{} path. +\item If you got the development version, move the \texttt{pixelart0.sty} file into a \LaTeX{} path. +\end{itemize} + +\section{Usage} +\label{sec:usage} + +\subsection{Package options} +\changes{v0.2.0}{2018/02/25}{Add package option \texttt{draft}.} + +This package has a single package option: |draft|. If this option is set (\lstinline|\usepackage[draft]{pixelart}|), pixel-art pictures are ignored. This can make compilation \emph{way, way} faster\footnote{On a document I am writing, containing a lot of pixel-art pictures, option |draft| makes compilation time go from 6 minutes to 22 seconds.}. + +A downside is that since pixel-art pictures are ignored, this can mess up your document layout. A nicer option would be to have option |draft| guess the pixel-art size, and display a dummy picture with the same size\footnote{This has been implemented in |pixelart|.}. + +\subsection{Macros} + +This package defines two macros : |\bwpixelart|\footnote{\texttt{$\backslash{}$bwpixelart} stands for \emph{b}lack and \emph{w}hite \emph{pixel art}, although \emph{color and transparent pixel art} would be more accurate.}, used to insert a pixel-art picture, and |\tikzbwpixelart|, which has the same purpose, excepted that it is called from within a |tikzpicture| environment. +\changes{v0.1.2}{2018/01/13}{First line-break of pixelart argument is now automatically ignored.} + +\subsubsection{\textbackslash\texttt{bwpixelart}} +\DescribeMacro{\bwpixelart} +To insert a pixel-art picture in your text, use : +\begin{center} + \lstinline|\bwpixelart|\oarg{color, raise, scale}\marg{pixels} +\end{center} +Its optional arguments are: +\begin{description} +\item[color=black] Foreground color (the background is transparent); +\item[scale=1] Scale. By default, a pixel is the size of a |tikzpicture| default unit, which is probably bigger than what you want. +\item[raise=0pt] Raise the picture. By default, the bottom of the picture is on the baseline. You might want to lower it a little by giving this option a negative argument. +\end{description} + +Its mandatory argument is the picture pixels, as |0|'s and |1|'s. Line breaks in this argument are interpreted as line breaks in the pixel art pictures. How spaces are interpreted is undefined (see section \ref{ssec:spaces} for more information). + +For instance, this heart +\bwpixelart[color=red, scale=.05, raise=-1ex]{% +001101100 +011111110 +111111111 +111111111 +111111111 +011111110 +001111100 +000111000 +000010000 +} +was drawn using the following code: + +\begin{lstlisting} + \bwpixelart[color=red, scale=.05, raise=-1ex]{% + 001101100 + 011111110 + 111111111 + 111111111 + 111111111 + 011111110 + 001111100 + 000111000 + 000010000 + } +\end{lstlisting} + + \subsubsection{\textbackslash\texttt{tikzbwpixelart}} + \DescribeMacro{\tikzbwpixelart} + The second macro, |\tikzbwpixelart| is almost identical to the first one, excepted that it is meant to be called from inside a |tikzpicture| environment. Actually, \lstinline|\bwpixelart{0101}| is more or less equivalent to calling : + + \begin{lstlisting} +\begin{tikzpicture} + \tikzbwpixelart{(0, 0)}{0101} +\end{tikzpicture} +\end{lstlisting} + + The signature of this macro is : + \begin{center} + \lstinline|\tikzbwpixelart|\oarg{color, scale}\marg{coordinates}\marg{pixels} + \end{center} + Its optional arguments are |color| and |scale|, used to set the color and scale of the picture. + + Its first mandatory argument is the coordinate of the top left corner of the picture; the second one is the list of pixels (using the same syntax as the |\bwpixelart| macro). + + For instance, this heart +\begin{tikzpicture}[scale=.05, baseline=-1em] + \fill[red] (5, -4) circle (6.5); + \tikzbwpixelart{(0, 0)}{% + 0011001100 + 0111111110 + 1111111111 + 1111111111 + 1111111111 + 0111111110 + 0011111100 + 0001111000 + 0000110000 +} +\end{tikzpicture} + was drawn using the following code: + +\begin{lstlisting} +\begin{tikzpicture}[scale=.05, baseline=-1em] + \fill[red] (5, -4) circle (6.5); + \tikzbwpixelart{(0, 0)}{% + 0011001100 + 0111111110 + 1111111111 + 1111111111 + 1111111111 + 0111111110 + 0011111100 + 0001111000 + 0000110000 +} +\end{tikzpicture} +\end{lstlisting} + +\section{Bugs, Ideas, Undefined behaviours} +\label{sec:bugs} + +\marginpar{Note that most of the stuff in this section have been fixed in the version 1.0.0 of \textsf{pixelart}.} + I have great ideas about what this package could do, but: + \begin{itemize} + \item I do not need them; + \item I am not sure there is a huge \emph{need} for some pixel-art package; + \item I have a full-time job, my wife has a far-more-than-full-time job, my daugther \emph{is} a full-time job\footnote{She has grown up, and I can get more sleep and more free time now, which explains |pixelart| version 1.0.0!}, so I have very little time to hack… + \end{itemize} + + So, I am listing here some known bugs, undefined behaviours, limitations. + + \subsection{Missing \texttt{\textbackslash{}pixelart} macro} + + There is no |\pixelart| macro. This is on purpose: given that this package is more or less a working draft, I did not want to register a badly designed |\pixelart| macro. This means that some folk wanting to improve this package can extand the |\bwpixelart| macro and use the name |\pixelart| to fix my design mistakes. + + \subsection{It's insanely slooooow.} + + That's it. It takes alomst 30 seconds to compile a document containing only a $128\times128$ picture (about \numprint{16000} pixels). I have no idea how to fix it. Good luck. + + \subsection{Black and white} + + Right now, it is black and white only (or, to be more accurate, any single color on a transparent background). + + One \emph{could} produce colored pixel-art pictures, but… it's complicated. For instance, this heart (borrowed from the Django project\footnote{\url{https://www.djangoproject.com/}}): + + \definecolor{violet1}{RGB}{247, 176, 207} + \definecolor{violet2}{RGB}{238, 33, 120} + \definecolor{violet3}{RGB}{214, 45, 117} + \definecolor{violet4}{RGB}{217, 25, 92} + \definecolor{violet5}{RGB}{173, 29, 69} + \begin{center} + \begin{tikzpicture}[scale=.1] + \tikzbwpixelart[color=violet1]{(0, 0)}{% + 0000000 + 0000010 + } + \tikzbwpixelart[color=violet2]{(0, 0)}{% + 0000000 + 0110100 + 0000000 + 0010100 + 0000000 + 0001000 + } + \tikzbwpixelart[color=violet3]{(0, 0)}{% + 0000010 + 0000000 + 1000010 + 0000000 + 0001000 + } + \tikzbwpixelart[color=violet4]{(0, 0)}{% + 0010100 + 1001000 + 0110100 + 0001010 + 0010100 + } + \tikzbwpixelart[color=violet5]{(0, 0)}{% + 0100000 + 0000001 + 0001001 + 0100000 + } + \end{tikzpicture} + \end{center} + + could be produced using the following code. Basically (given that colors |violet1| to |violet5| have been correctly defined), we stack up several single-color pixel-art pictures. + +\begin{lstlisting} +\begin{tikzpicture}[scale=.1] + \tikzbwpixelart[color=violet1]{(0, 0)}{% + 0000000 + 0000010 + } + \tikzbwpixelart[color=violet2]{(0, 0)}{% + 0000000 + 0110100 + 0000000 + 0010100 + 0000000 + 0001000 + } + \tikzbwpixelart[color=violet3]{(0, 0)}{% + 0000010 + 0000000 + 1000010 + 0000000 + 0001000 + } + \tikzbwpixelart[color=violet4]{(0, 0)}{% + 0010100 + 1001000 + 0110100 + 0001010 + 0010100 + } + \tikzbwpixelart[color=violet5]{(0, 0)}{% + 0100000 + 0000001 + 0001001 + 0100000 + } +\end{tikzpicture} +\end{lstlisting} + + One could imagine a simpler syntax: we assign several colors to characters, and we use |1|, |2|, |3|, etc. as the pixels to define the picture. This would give the following code. + +\begin{lstlisting} +\begin{tikzpicture}[scale=.1] + \tikzpixelart[colors={ + 1=violet1, + 2=violet2, + 3=violet3, + 4=violet4, + 5=violet5, + }]{(0, 0)}{% + 0540430 + 4224215 + 3445435 + 0524240 + 0043400 + 0002000 + } +\end{tikzpicture} +\end{lstlisting} + + \subsection{Spaces} +\label{ssec:spaces} + + Spaces are interpreted as line breaks. For instance, this heart + \bwpixelart[scale=.03, raise=-1pt]{% + 0011001100 0111111110 1111111111 + 1111111111 1111111111 0111111110 + 0011111100 0001111000 0000110000 + } + could be written as : + +\begin{lstlisting} +\bwpixelart[scale=.03, raise=-1pt]{% + 0011001100 0111111110 1111111111 + 1111111111 1111111111 0111111110 + 0011111100 0001111000 0000110000 +} +\end{lstlisting} + + This will work (right now), but is an undefined behaviour, and might change in a later version without prior notice. + + \subsection{Uneven lines} + + Right now, lines do not \emph{have} to have the same number of characters. For instance, the following heart + \bwpixelart[scale=.03, raise=-1pt]{% + 00110011 + 011111111 + 1111111111 + 1111111111 + 1111111111 + 011111111 + 00111111 + 0001111 + 000011 +} + could be written as : + +\begin{lstlisting} +\bwpixelart[scale=.03, raise=-1pt]{% + 00110011 + 011111111 + 1111111111 + 1111111111 + 1111111111 + 011111111 + 00111111 + 0001111 + 000011 +} +\end{lstlisting} + + This is an undefined behaviour and might raise an error in the future. + +\changes{v0.1.0}{2017/12/05}{First published version.} + +\addcontentsline{toc}{section}{Change History} +\PrintChanges + +\addcontentsline{toc}{section}{Index} +\PrintIndex + +\end{document} -- cgit v1.2.3