A small display of a scientific calculator

Starting from LCD package (one page) of documentation, looking in particular this question where there is the long code of @Thomas F. Sturm (here):,

\documentclass[openany,10pt]{book}

\usepackage{newpxtext}

\usepackage[varg]{newpxmath} %font package

\usepackage[letterpaper,margin=0.75in,bindingoffset=0.5in]{geometry}

\usepackage[most]{tcolorbox}
\colorlet{blackened}{black!90!white}
\colorlet{blackish}{black!70!white}
\colorlet{greyish}{black!60!white}
\colorlet{whiteish}{white}
\colorlet{orangeish}{yellow!90!red}
\colorlet{greenish}{green!16!gray}
\colorlet{redish}{red!80!black}

\tcbset{calbackground/.style={
enhanced,
leftright skip=0.25cm,beforeafter skip=0pt,
toptitle=0mm,bottomtitle=0mm,
right=2mm,left=2mm,
top=1pt,
bottom=0.25cm,
boxsep=0pt,
boxrule=0mm,
sharp corners,
sidebyside,
sidebyside gap=2mm,
lefthand ratio=0.6,
bicolor,
colback=black!10!white,
colbacklower=greenish,
colframe=white,
autoparskip,
}}

\newtcbtheorem[no counter]{calx}{Calculator}{calbackground}{cax}

\newtcbox{\KY}[1][]{
enhanced,
on line,
arc=2pt,outer arc=2pt,
boxrule=0pt,bottomrule=0.25mm,rightrule=0.2mm,
boxsep=0pt,left=0pt,right=0pt,top=1pt,bottom=1pt,
interior style={top color=blackish,bottom color=blackened},
colframe=greyish,
width=2.5em,
tcbox width=forced center,
equal height group=K,
valign=center,
fontupper=\footnotesize\sffamily,
coltext=orangeish,
before upper=\vrule width 0pt height 2ex depth 1ex\relax,
}

\newtcbox{\KYm}[1][]{
enhanced,
on line,
arc=2pt,outer arc=2pt,
boxrule=0pt,bottomrule=0.25mm,rightrule=0.2mm,
boxsep=0pt,left=0pt,right=0pt,top=1pt,bottom=1pt,
interior style={top color=blackish,bottom color=blackened},
colframe=greyish,
width=2.5em,
tcbox width=forced center,
equal height group=K,
valign=center,
fontupper=\footnotesize\sffamily,
coltext=orangeish,
before upper=\vrule width 0pt height 2ex depth 1ex\relax$, after upper=$,
}

\newtcbox{\KN}{
enhanced,
on line,
arc=2pt,outer arc=2pt,
boxrule=0pt,bottomrule=0.25mm,rightrule=0.2mm,
boxsep=0pt,left=0pt,right=0pt,top=1pt,bottom=1pt,
interior style={top color=blackish,bottom color=blackened},
colframe=greyish,
width=1.5em,
tcbox width=forced center,
equal height group=K,
valign=center,
fontupper=\footnotesize\sffamily,
coltext=whiteish,
before upper=\vrule width 0pt height 2ex depth 1ex\relax,
}

\usepackage{lcd}
\LCDcolors{black}{greenish}
\DefineLCDchar{sq}{11100001000100011100000000000000000}
\DefineLCDchar{tm}{00000100010101000100010101000100000}
\DefineLCDchar{dv}{00000001000000011111000000010000000}
\DefineLCDchar{mu}{00011000011110100001000000000000000}
\DefineLCDchar{sc}{11011010011001000000000000000000000}

\DeclareMathOperator{\ee}{\textrm{e}}

\usepackage{MnSymbol} %boxes
\usepackage{xfrac} %sfrac
\usepackage{lipsum} %for textwidth comparison
\setlipsumdefault{1-2}

\begin{document}

\begin{calx}{}{}
\KY{$($}\KN{3}\KY{$x^2$}\KN{-}\KN{4}\KY{$x^2$}\KN{-}\KN{6}\KY{$x^2$}\KY{$)$}\KN{$=$}
\tcblower
{\Large\textLCD[0]{20}|(3{sq}-4{sq}-6{sq})|}
{\LARGE\textLCD[0]{16}|             -43|}
\end{calx}
%
\begin{calx}{}{}
\KN{$\div$}\KY{$($}\KY{$(-)$}\KN{2}\KN{$\times$}\KN{4}\KN{$\times$}\KN{6}\KY{$)$}\KN{$=$}
\tcblower
{\Large\textLCD[0]{20}|ANS{dv}(-2{tm}4{tm}6)|}
{\LARGE\textLCD[0]{16}|    0.8958333333|}
\end{calx}
%
\begin{calx}{}{}
\KY{$\cos^{-1}$}\KY{ANS}\KN{$=$}
\tcblower
{\Large\textLCD[0]{20}|cos{mu}(ANS|}
{\LARGE\textLCD[0]{16}|     26.38432975|}
\end{calx}
%
\begin{calx}{}{}
\KY{$\circ\,\prime\,\prime\prime$}
\tcblower
{\Large\textLCD[0]{20}|cos{mu}(ANS|}
{\LARGE\textLCD[0]{16}|     26°23'3.59{sc} |}
\end{calx}

\lipsum

\KYm{x^2}%
\KYm{x^3}%
\KYm{x^{-1}}%
\KYm{x^{\filledsquare}}%
\KYm{\sqrt{\filledmedsquare}}%
\KYm{\sqrt[3]{\filledmedsquare}}%
\KYm{\sqrt[\filledsquare]{\medsquare}}\\

\KY{$\ln$}%
\KY{$\log$}%
\KY{$\log_{\filledsquare}\medsquare$}%
\KY{$10^{\filledsquare}$}%
\KY{$\ee^{\filledsquare}$}\\

\KY{$(-)$}%
\KY{$\frac{\filledmedsquare}{\medsquare}$}%
\KY{$\sfrac{\filledmedsquare}{\medsquare}$}%
\KY{$\tfrac{\filledmedsquare}{\medsquare}$}\\

\KY{$\circ\,\prime\,\prime\prime$}%
\KY{$\sin$}%
\KY{$\sin^{-1}$}%
\KY{$\cos$}%
\KY{$\cos^{-1}$}%
\KY{$\tan$}%
\KY{$\tan^{-1}$}\\

\KY{$($}%
\KY{$)$}%
\KN{$\times$}%
\KN{$\div$}%
\KN{$+$}%
\KN{$-$}%
\KN{$=$}\\

\KN{$1$}%
\KN{$2$}%
\KN{$3$}%
\KN{$4$}%
\KN{$5$}%
\KN{$6$}%
\KN{$7$}%
\KN{$8$}%
\KN{$9$}%
\KN{$0$}\\

\KN{1}%
\KN{2}%
\KN{3}%
\KN{4}%
\KN{5}%
\KN{6}%
\KN{7}%
\KN{8}%
\KN{9}%
\KN{0}\\

\end{document}


how can I reduce the MWE adding only the words DEG or RAD in character LCD, increasing the dimension of the rectangle (height and lenght)?

Thank you very much for all users.

Related question for the symbols of the calculator: Easiest way to create TeX macro/code to access symbols from particular font?

• @downvoter: Please can you explain me the reason of your downvote? Sep 27, 2020 at 22:15
• Not sure if I understand your requirement. Do you want to 1) simplify the code, 2) add either of word DEG or RAD to show the format of computation, and 3) increasing the dimension (characters per line, not pixels per character) of emulated calculator screen? Sep 28, 2020 at 0:29
• @muzimuzhiZ Hi, 1) and 2) are correct. Increasing the rectangular dimension, i.e. increasing the height, with DEG and RAD, cos, etc... all in pixel fonts, like if I had a true display. Please, can you edit my question for to be more clear? Thank you very much. Sep 28, 2020 at 11:50
• It is not a pixel font, but a set of figures composed by small filled squares (5 per line with 7 lines) which are manually encoded character per character, see \DefineLCDchar{sq}{...} in your mwe. So more pixels per character means more manual work. Sep 28, 2020 at 12:11
• @muzimuzhiZ I have put himself DEG and RAD manually with Paint of OS Windows. I am not able to understand if they are pixel font or no. I thinked yes. :-( Excuse me. For me it is important that it will be similar to a calculator. No more work for you. I have deleted the tag pixelated. Thank you for your comprension. Sep 28, 2020 at 12:17

Possibly, this is irrelevant. Since the LCD package can only render a limited set of pre-defined glyphs, why don't we just pixelate standard LaTeX's output and use it as our LCD screen? The workflow is summarized as below:

1. Use LaTeX to render LCD screen content (as if they are normal text)
2. Use convert to transform PDF files into images
3. Pixelate the screen content based on the image
4. Re-render the LCD screen in LaTeX

The result is shown as below:

Usage

• Place preamble.tex,lcd_test.tex and lcd.py under the same folder.
• Run lcd.py (Tested on Linux. It will not work on Windows because convert collides with Windows' existing system command.)

Problems

1. It compiles extremely slow. That is the reason why I tried to save the LCD screen as individual PDF file. It is slow because I am using TikZ to draw all these dots on the screen. It can be facilitated after proper optimization.
2. Due to the naive pixelation approach, weird aliasing is likely to occur. One may try to find better fonts or come up with better pixelation parameters to alleviate this issue.

Source

preamble.tex

\usepackage[skins]{tcolorbox}
\usepackage{xcolor}
\definecolor{lcdcolor}{HTML}{6b946b}

\newlength{\lcdwidth}
\newlength{\lcdheight}
\setlength{\lcdwidth}{6cm}
\setlength{\lcdheight}{2.0cm}

\newtcolorbox{lcdscreen}{
enhanced,
colframe=lcdcolor,
colback=lcdcolor
}

\newtcolorbox{lcdbox}{
enhanced,
colback=white,
boxrule=0pt,
frame hidden,
boxsep=0pt,
width=\lcdwidth,
height=\lcdheight,
arc=0pt,
sharp corners,
before upper={\begin{minipage}[t][\lcdheight]{\lcdwidth}\bgroup\lsstyle\Large},
after upper={\egroup\end{minipage}},
top=0mm,
bottom=0mm,
left=0mm,
right=0mm
}


lcd_test.tex

\documentclass{standalone}
\input{preamble.tex}
\usepackage{expl3}

\ExplSyntaxOn
\dim_new:N \l_lcd_pixel_dist_dim
\dim_set:Nn \l_lcd_pixel_dist_dim {0.15mm}
\dim_new:N \l_lcd_pixel_size_dim
\dim_set:Nn \l_lcd_pixel_size_dim {0.3mm}

\tikzset{
pixelnode/.style={
inner~sep=0mm,
outer~sep=0mm,
minimum~width=\l_lcd_pixel_size_dim,
minimum~height=\l_lcd_pixel_size_dim,
anchor=north~west,
fill=black
}
}

\fp_new:N \l_i_fp
\fp_new:N \l_j_fp

\newcommand{\drawlcd}[1]{
\ior_open:Nn \g_tmpa_ior {#1}
\ior_str_map_variable:NNn \g_tmpa_ior \l_tmpa_tl {
\clist_set:NV \l_tmpa_clist \l_tmpa_tl
\exp_args:NNx \fp_set:Nn \l_i_fp {\clist_item:Nn \l_tmpa_clist {1}}
\exp_args:NNx \fp_set:Nn \l_j_fp {\clist_item:Nn \l_tmpa_clist {2}}
\fp_set:Nn \l_tmpa_fp { \l_i_fp * \l_lcd_pixel_size_dim + \l_i_fp * \l_lcd_pixel_dist_dim}
\fp_set:Nn \l_tmpb_fp { \l_j_fp * \l_lcd_pixel_size_dim + \l_j_fp * \l_lcd_pixel_dist_dim}
\node[pixelnode] at (\fp_use:N \l_tmpb_fp pt, \fp_use:N \l_tmpa_fp pt) {};
}
\ior_close:N \g_tmpa_ior
}

\ExplSyntaxOff

\begin{document}%
\begin{lcdscreen}%
\begin{tikzpicture}%
\drawlcd{temp.txt}
\end{tikzpicture}%
\end{lcdscreen}%
\end{document}


lcd.py

import subprocess
from PIL import Image
import numpy as np
import matplotlib.pyplot as plt

latex_template = r'''
\documentclass{standalone}
\input{preamble.tex}
\usepackage{cmbright}
\usepackage{amsmath, amssymb}
\usepackage[letterspace=100]{microtype}
\begin{document}%
\begin{lcdbox}%
%%content
\end{lcdbox}%
\end{document}
'''

screen_rows = 80
screen_cols = 240

def pixelate(content):
latex_doc = latex_template.replace('%%content', content)
with open('temp.tex', 'w') as outfile:
outfile.write(latex_doc)
# run pdflatex to compile the document
subprocess.run(['pdflatex', '-interaction=nonstopmode', 'temp.tex'])
# convert pdf to image
subprocess.run(['convert', '-density', '800', 'temp.pdf','temp.png'])

image = np.asarray(Image.open('temp.png')).astype(np.float32) / 255.0
if len(image.shape) > 2:
image = image[:, :, 0]

iticks = np.round(np.linspace(0, image.shape[0], screen_rows + 1)).astype(np.int)
jticks = np.round(np.linspace(0, image.shape[1], screen_cols + 1)).astype(np.int)
downsampled = np.zeros((screen_rows, screen_cols), np.bool)

for i in range(len(iticks) - 1):
rows = image[iticks[i]:iticks[i+1],:]
for j in range(len(jticks) - 1):
col = rows[:, jticks[j] : jticks[j + 1]]
if col.min() < 0.9:
downsampled[i,j] = True

#plt.imshow(downsampled);plt.show()

downsampled = np.flip(downsampled, axis=0)
pixel_locations = np.where(downsampled)
with open('temp.txt', 'w') as outfile:
for i in range(pixel_locations[0].size):
outfile.write('{},{}\n'.format(pixel_locations[0][i], pixel_locations[1][i]))

subprocess.run(['pdflatex', '-interaction=nonstopmode', 'lcd_test.tex'])

pixelate(r'''$\displaystyle \int_a^b \frac{x^2+3x+5}{3\sin x} dx$\\
\vfill
English\hfill 12345.0''')

• You have done lot lot lot work ....and I hope to that other users reward you. Always thank you from the heart; I am not at all skillful with python and expl3. Sep 29, 2020 at 7:51
• @downvoter: What is the reason for a downvote? Sep 29, 2020 at 9:41
• @Sebastiano Grazie! I really appreciate your compliment. Python is like my survival skills; but it only takes my a month to learn expl3! I am also writing a tutorial on expl3. Sep 29, 2020 at 13:41
• @Sebastiano How do you like this solution? Probably it is a bit heavy-weight. Sep 29, 2020 at 13:43
• @AlanXiang Sorry for barge in the topic, but I would definitely love to see your tutorial on expl3! Sep 30, 2020 at 7:12

Here's my attempt at simplifying things and adding in the DEG and RAD. I've made it so that RAD and DEG will always appear in the same place as they would on a real calculator. You could easily add other flags that might be needed (e.g., OCT and HEX) in the same manner.

The way the lcd package boxes things up is … odd. I found that it behaved in a reasonably sensible way in a table, so I wrapped the lower tcolorbox in a tabular environment.

I couldn't be bothered making all the size calculations automatic, but it's not too much of a pain to adjust things.

Since you say you are happy with the calculator keys, I haven't worried about them.

\documentclass{article}

\usepackage{amsmath}
\usepackage[most]{tcolorbox}
\usepackage{lcd}

\colorlet{greenish}{green!16!gray}

\LCDcolors{black}{greenish}
\LCDnoframe
\renewcommand*\textLCDcorr{0}
\DefineLCDchar{sq}{11100001000100011100000000000000000}
\DefineLCDchar{tm}{00000100010101000100010101000100000}
\DefineLCDchar{dv}{00000001000000011111000000010000000}
\DefineLCDchar{mu}{00011000011110100001000000000000000}
\DefineLCDchar{"}{11011010011001000000000000000000000}
\DefineLCDchar{deg}{01100100101001001100000000000000000}

\newcommand{\DEG}{\llap{DEG\hspace{10mm}}}

\newtcolorbox{calc}[1][]{
enhanced,bicolor,
boxsep=0pt,
boxrule=0pt,
top=6pt,bottom=0pt,left=6pt,right=0pt,
sharp corners,
frame empty,
colback=black!10,
colbacklower=greenish,
sidebyside,
sidebyside align=top seam,
sidebyside gap=0pt,
righthand width=50.7mm,
before lower=\begin{tabular}{@{}l@{}},
after lower=\end{tabular},
overlay={\node[inner sep=0pt, outer sep=0pt, text height=5pt, text
depth=1pt, text width=50.7mm, fill=greenish, anchor=north
east, font=\sffamily\tiny\bfseries, align=flush right]
at (frame.north east) {#1};}
}

\begin{document}

$(3x^2-4x^2-6x^2)=$
\tcblower
\large\textLCD{19}|(3{sq}-4{sq}-6{sq})| \\
\Large\textLCD{16}|             -43| \\
\end{calc}

\begin{calc}[\DEG]
$\div(-2\times4\times6)=$
\tcblower
\large\textLCD{19}|ANS{dv}(-2{tm}4{tm}6)| \\
\Large\textLCD{16}|    0.8958333333| \\
\end{calc}

\begin{calc}
$\cos^{-1}\text{ANS}=$
\tcblower
\large\textLCD{19}|cos{mu}(ANS| \\
\Large\textLCD{16}|     26.38432975| \\
\end{calc}

$\cos^{-1}\text{ANS}=$