28 Commits

Author SHA1 Message Date
Marc Wäckerlin 5d529cd035 fix ADDR bug 2026-05-01 17:16:22 +02:00
Marc Wäckerlin 1e1d862688 first iteration of layout correction 2026-05-01 15:49:45 +02:00
Marc Wäckerlin 12ada37901 review and cleanup 2026-05-01 11:46:17 +02:00
Marc Wäckerlin 1d581d3978 improved header typography 2026-04-30 20:52:37 +02:00
Marc Wäckerlin 9cebbd80db new headre emphasis 2026-04-30 19:43:03 +02:00
Marc Wäckerlin 4c8a24fcf4 layout fix 2026-04-30 18:46:28 +02:00
Marc Wäckerlin 1bfdbafc27 more layout options 2026-04-30 17:34:16 +02:00
Marc Wäckerlin 7de0ed5466 work from autumn 2026-04-29 15:35:03 +02:00
Marc Wäckerlin f7b9202b31 logo can be an image or a LaTeX element 2025-11-11 18:19:29 +01:00
Marc Wäckerlin 5a8b2d8677 zwischenstand 2025-11-11 17:09:12 +01:00
Marc Wäckerlin 06e57b546f new feature color for text color 2025-11-11 15:41:36 +01:00
Marc Wäckerlin 29ce75ecf1 bugs fixed 2025-11-11 15:11:28 +01:00
Marc Wäckerlin 65335f7981 fixed image company logo 2025-11-11 11:50:36 +01:00
Marc Wäckerlin dd330d412c fix LaTeX object in logo 2025-11-11 10:53:12 +01:00
Marc Wäckerlin a4480da3b9 add feature use image for companylogo 2025-11-10 17:00:14 +01:00
Marc Wäckerlin d99e4d0872 fix display bug if no company is set; improve title width vs. logo wodthy 2025-11-10 14:00:34 +01:00
Marc Wäckerlin dd92e3c5df Add Title Role 2025-11-10 13:07:52 +01:00
Marc Wäckerlin 793c7f9360 options updated, local options added 2025-11-09 17:24:30 +01:00
Marc Wäckerlin b11a347034 logo has good default and is freely stylable 2025-11-09 12:51:22 +01:00
Marc Wäckerlin eaa40a3901 adapt logo height to number of lines 2025-11-09 12:08:18 +01:00
Marc Wäckerlin 7de41206fd rename additionalnames to company and set on second line 2025-11-09 11:51:02 +01:00
Marc Wäckerlin eb1e9451e9 rename photo to logo 2025-11-09 11:17:49 +01:00
Marc Wäckerlin 07898c33a1 fix build 2025-11-09 11:03:42 +01:00
Marc Wäckerlin af2a53a9d9 background opacity fixed 2025-11-09 09:45:42 +01:00
Marc Wäckerlin 2c2fbdbe9e added background with opacity to QR-Code and card; bug in card opacity 2025-11-09 09:08:09 +01:00
Marc Wäckerlin 407c7eed2d country with city if short 2025-11-08 19:11:43 +01:00
Marc Wäckerlin 0f802a02a8 added image in qr-code or next to name - improvements 2025-11-08 17:30:48 +01:00
Marc Wäckerlin 9c4d85528a added image in qr-code or next to name 2025-11-08 17:09:38 +01:00
70 changed files with 1896 additions and 321 deletions
+58
View File
@@ -0,0 +1,58 @@
# LaTeX auxiliary files
*.aux
*.log
*.out
*.toc
*.synctex*
*.fdb_latexmk
*.fls
*.xdv
*.nav
*.snm
*.vrb
# Build directories
.texpadtmp/
*.d/
# Generated PDFs (comment out if you want to track them)
# *.pdf
# Autotools
/autom4te.cache/
/aclocal.m4
/compile
/config.guess
/config.h.in
/config.sub
/configure
/depcomp
/install-sh
/ltmain.sh
/missing
/texmf-dist/
*.tar.gz
*.tar.bz2
*.tar.xz
# Autoconf generated files
/config.status
/config.log
Makefile
makefile
makefile.in
/examples/makefile
/examples/makefile.in
/screenshots/makefile
/screenshots/makefile.in
# Backup files
*~
*.bak
*.swp
*.swo
\#*\#
# OS specific
.DS_Store
Thumbs.db
+21
View File
@@ -0,0 +1,21 @@
use strict;
use warnings;
use Cwd qw(abs_path);
use File::Basename qw(dirname);
use File::Spec;
BEGIN {
return if $ENV{'BCQ_TEXINPUTS_SET'};
my $repo_root = dirname(abs_path(__FILE__));
my $examples_dir = File::Spec->catdir($repo_root, 'examples');
my $existing = $ENV{'TEXINPUTS'};
if (defined $existing && length $existing) {
$ENV{'TEXINPUTS'} = join(':', $repo_root, $examples_dir, $existing);
} else {
$ENV{'TEXINPUTS'} = join(':', $repo_root, $examples_dir, '');
}
$ENV{'BCQ_TEXINPUTS_SET'} = 1;
}
+3
View File
@@ -0,0 +1,3 @@
{
"makefile.configureOnOpen": false
}
+421 -164
View File
@@ -1,172 +1,30 @@
Businesscard with QR-Code Businesscard with QR-Code
========================= =========================
What happens, if you give your visiting card to someone? Either he manually types the text into his computer or mobilefone, or it will end up in a box and be forgotten. Nowadays data is required electronically, not on paper. Here is the solution: A visiting card with QR-Code that contains a full [vcard], so that it can be scanned with an [app] on the mobilefone and therefore automatically imported into the electronic contacts. This also works well, when you are offline and bluetooth transfer fails. So here is the highly configurable businescard or visitingcards with full [vcard] as QR-Code, ready to send to online printers. You can specify the exact size of the paper and the content within the paper, inluding generation of crop marks. What happens when you hand someone a business card? Either they type everything manually, or the card gets forgotten. This class generates a print-ready business card with a QR code that embeds a full [vcard], so contact data can be imported directly with a scanner [app].
Other available visitingcard templates, such as [mschlenker] distribute the cards on an A4 paper. But if you want a professional printer, such as [onlineprinters], then you need to be able to generate a PDF with exactly one card, an exactly defined border and crop marks. Compared to templates that place many cards on A4, this project focuses on professional printing workflows: one card per PDF page, exact dimensions, and crop marks.
[![Example: John Doe from Hongkong](screenshots/john-doe-hongkong.jpg)](examples/john-doe-hongkong.tex) [![Example: John Doe from Hongkong](screenshots/john-doe-hongkong.png)](examples/john-doe-hongkong.tex)
[![Example: Businesscard of Peter Muster from Zürich](screenshots/peter-muster-example-company-zuerich.jpg)](examples/peter-muster-example-company-zuerich.tex) [![Example: Businesscard of Peter Muster from Zürich](screenshots/peter-muster-example-company-zuerich.png)](examples/peter-muster-example-company-zuerich.tex)
[![Example: Nearly Real Examle Of My Card](screenshots/example.jpg)](examples/example.tex) [![Example: Nearly Real Example Of My Card](screenshots/example.png)](examples/example.tex)
Features Features
======== ========
- all information is in the QR-Code - full contact payload in QR code (vCard 4.0)
- full privacy control: input is optional, specify only what you need, you decide what information to share, e.g. I print three cards, with phone and address, without address and only with electronical contacts, no phone nor address - privacy control per field via optional `[hide]` (in QR only, not printed)
- optional icons, optional small hint texts - configurable layout: alignment, icon placement, text/QR order, spacing, card dimensions
- several alignments - professional print output with crop marks and exact paper/content size
- freely defined size of paper and content - visual customization: logos, QR-center logo, background image/color, text color, QR color
- supports honoric titles, full names, address with post office box and extended information - social/contact integrations ([jabber], [matrix], [gitea], [github], [git], [facebook], [twitter], [youtube], [wikipedia], [nextcloud federation id])
- supports telefone, email, [jabber] and [matrix] chat - PGP key URL and fingerprint support
- supports several urls for your hompages - multi-page PDFs (e.g. front/back variants) with `\newcard`
- supports [gitea], [github], [git]
- supports [facebook], [twitter], [google+], [youtube], [wikipedia]
- supports [pgp] key url and fingerprint
- supports [nextcloud federation id]
Usage Quick Start
===== ===========
Installation
------------
Copy `businesscard-qrcode/businesscard-qrcode.cls` to your LaTeX class path. Simplest way for installation on Linux:
```bash
mkdir ~/texmf/tex/latex/businesscard-qrcode
cp businesscard-qrcode/businesscard-qrcode.cls ~/texmf/tex/latex/businesscard-qrcode/
```
Compilation
------------
**Important:** You must use **`xelatex`** for compilation, because `xelatex` properly supports UTF-8 (e.g. needed for german umlauts or chinese characters). The package `inputenc` messes up with package `qrcode`.
Document Structure
------------------
```latex
\documentclass[<layout-options>]{businesscard-qrcode}
<data-definitions>
\begin{document}
\drawcard
\end{document}
```
where `<layout-options>` and `<data-definitions>` are explained below.
Layout Options
--------------
Layout options are set as options to the `\documentclass`, e.g.:
\documentclass[textwidth=0.7,qrwidth=0.25,www,nofill,iconright,rightalign,hint,icon,textfirst]{businesscard-qrcode}
### Available Options:
- `paperwidth=`: width of the physical paper where the card is printed on (incl. border), default: `89mm`
- `paperheight=`: height of the physical paper where the card is printed on (incl. border), default: `59mm`
- `contentwidth=`: width of the card's content without the border that is cut, default: `85mm`
- `contentheight=`: height of the card's content without the border that is cut, default: `55mm`
- `fontsize=`: any fontsize allowed in `extarticle`, that are `8pt`, `9pt`, `10pt`, `11pt`, `12pt`, `14pt`, `17pt` and `20pt`, default: `8pt`
- `padding=`: padding within the card's content, default: `2mm`
- `cutdist=`: distance in `mm` where the cut marks are set, default: `2`
- `cutlen=`: length of the cut marks in `mm`, default: `1`
- `textwidth=`: relative width of the text block `1` means full width, so `qrwidth` plus `textwidth` should be smaller than `1` the remainig space is left empty between the text and QR-Code, default: `0.55` (that's 55% of the available space)
- `qrwidth=`: relative width of the QR-Code `1` means full width, so `qrwidth` plus `textwidth` should be smaller than `1` the remainig space is left empty between the text and QR-Code, default: `0.40` (that's 40% of the available space)
- `lang=`: language of the wikipedia page, will be prepended before `wikipedia.org`, e.g. `de.wikipedia.org`, default: `de`
- `address`or `noaddress`: disable rendering of the address in text and QR-Code, default: address
- `hint` or `nohint`: show the little text hints, default: `hint`
- `icon` or `noicon`: show the icons, default: `icon`
- `rightalign` or `leftalign`: align text left or right, default: `rightalign`
- `iconleft` or `iconright`: show icon left or right of the text, default: `iconleft`
- `fill` or `nofill`: fill empty space between icon and text, default: `fill`
- `qrfirst` or `textfirst`: switch position of QR-Code and text block, default: `qrfirst`
- `https` or `www`: should links in the hints be prefixed with `https://` or `www.`, default: `https`
Data Definitions
----------------
Your data is entered with commands in the document, e.g.:
\email{name@example.com}
**Important:**: Spaces *must* be escaped by a backslash `\` in all data definitions, if they should be kept in the QR-Code. This is a limitation of the `qrcode`-package- Without escaping `\`, spaces are show in the text block, but not in the QR-Code. You may make use of this feature, if you do not escape the spaces in `\phone` and `\pgpfingerprint`, but everywhere else. This way, phone number and pgp fingerprint are condensed in the QR-Code.
See this example_
\givennames{Juan\ Pablo}
\familynames{Martínez\ Escudero}
\additionalnames{Example\ Company\ Ltd.}
\street{Im\ Stutz\ 123}
\pobox{Postfach\ 4567}
\phone{+41 52 123 45 67}
\pgpurl{https://pgp.mit.edu/pks/lookup?op=get\&search=0xF62315D04D4C0C62}
### Recognized Commands:
- `\type`: either `home` or `work` for personal or business cards
- `\givennames`: your first name and eventual middle names
- `\familynames`: your family names
- `\honoricprefix`: honorix name prefixes, e.g. academic titles
- `\honoricsuffix`: honoric name suffixes
- `\additionalnames`: additionl names — I use it for the company name in business cards
- `\pobox`: post office box
- `\extaddr`: address extension, e.g. name of a building or floor number
- `\street`: street and number of the address
- `\city`: name of the address location
- `\region`: region of the address
- `\zip`: zip code of the address
- `\country`: full name of country of the address in the language of the card
- `\phone`: your phone number, the phone is marked as mobile, so to be used for voice and text (SMS)
- `\email`: your email address
- `\jabber`: your [jabber] or xmpp chat address
- `\matrixorg`: your [matrix] chat addres, hint: use [riot] messenger for [matrix]
- `\cloud`: your [nextcloud federation id] — the url is prepended automatically
- `\homepage`: url to a web site with «home» icon — without `https://` not `www` (unless it is required), this is prepended automatically
- `\world`: url to a web site with «world» icon — without `https://` not `www` (unless it is required), this is prepended automatically
- `\link`: url to a web site with «link» icon — without `https://` not `www` (unless it is required), this is prepended automatically
- `\wordpress`: url to a web site with «wordpress» icon — without `https://` not `www` (unless it is required), this is prepended automatically
- `\drupal`: url to a web site with «» icon — without `https://` not `www` (unless it is required), this is prepended automatically
- `\joomla`: url to a web site with «joomla» icon — without `https://` not `www` (unless it is required), this is prepended automatically
- `\wikipedia`: if you or your company have a [wikipedia] entry, specify documentclass option `lang` for the language of you entry and use this definition for the name of your page — the url is prepended automatically
- `\git`: the url of your [git] repository — without `https://` not `www` (unless it is required), this is prepended automatically
- `\gitea`: the url of your [gitea] project page, you can use this tag also for other project management sites, such as [gogs] — without `https://` not `www` (unless it is required), this is prepended automatically
- `\github`: your account name on [github] — only the name of the account, the url is prepended automatically
- `\facebook`: your account name on [facebook] or the name of your page — only the name of the account or page, the url is prepended automatically
- `\twitter`: your account name on [twitter] — only the name of the account, the url is prepended automatically
- `\youtube`: your account name on [youtube] — only the name of the account, the url is prepended automatically
- `\google`: your account name on [google+] — only the name of the account, the url is prepended automatically
- `\pgpurl`: the full url to your pgp public key (only added to the QR-Code, not shown in the text)
- `\pgpfingerprint`: the fingerprint of your pgp public key
Print the Card
==============
The card is designed for professional printing service, such as [onlineprinters]. Please *check* the card and the *QR-Code* well before you pay money for printing! Choose a format, default is `89mm×59mm` with 2mm boder, so the card content is `85mm×55mm`. But the card can be adapted to any other printing format. To print cards of size `10cm×5cm` with `2mm` cut, you specify, [e.g.](examples/special-papersize.tex):
\documentclass[paperheight=5.4cm,paperwidth=10.4cm,
contentheight=5cm,contentwidth=10cm,
cutdist=2]
{businesscard-qrcode}
![example with special paper size](screenshots/special-papersize.jpg)
Usage Example
=============
Include the documentclass, define your data and add the document environment:
```latex ```latex
\documentclass{businesscard-qrcode} \documentclass{businesscard-qrcode}
@@ -182,24 +40,421 @@ Include the documentclass, define your data and add the document environment:
\email{name@example.com} \email{name@example.com}
\begin{document} \begin{document}
\drawcard \drawcard
\end{document} \end{document}
``` ```
Save it as file [texstudio_d30266.tex] and compile it to get [texstudio_d30266.pdf]: Compile with:
xelatex -synctex=1 -interaction=nonstopmode texstudio_d30266.tex ```bash
xelatex -interaction=nonstopmode your-card.tex
```
![the visiting card resulting from the usage example](screenshots/texstudio_d30266.jpg)
See [examples] for more examples. Installation
============
Copy `businesscard-qrcode/businesscard-qrcode.cls` to your LaTeX class path. Simplest way on Linux:
```bash
mkdir -p ~/texmf/tex/latex/businesscard-qrcode
cp businesscard-qrcode/businesscard-qrcode.cls ~/texmf/tex/latex/businesscard-qrcode/
ln -s ~/texmf/tex/latex ~/texmf/tex/xelatex
```
Compilation Notes
=================
- Use **`xelatex`** (UTF-8 support, e.g. umlauts, CJK).
- Do **not** load `inputenc` with this class.
- vCard line endings default to CRLF (`crlf` option) for better iOS import compatibility.
### Building with latexmk / IDEs
Editors such as VS Code LaTeX Workshop usually call `latexmk` from the workspace root. This repository ships project-local `.latexmkrc` files (root and `examples/`) that extend `TEXINPUTS` so TeX prefers the local class file from this checkout.
If you invoke `xelatex` manually without `latexmk`, set:
```bash
TEXINPUTS=/path/to/businesscard-qrcode:
```
(or run from the repository root).
Document Structure
==================
```latex
\documentclass[<layout-options>]{businesscard-qrcode}
<data-definitions>
\begin{document}
\drawcard
\end{document}
```
Escaping Spaces in Data
=======================
Spaces inside macro arguments must be escaped as `\ `, otherwise TeX may collapse them before QR/vCard generation.
```latex
\company{Example\ Company\ Ltd.}
\city{New\ York}
\phone{+41\ 44\ 123\ 45\ 67}
```
Layout Options
==============
You can set layout options in four ways:
1. `\documentclass[...]` (global defaults)
2. `\cardsetup{key=value,...}` (runtime/global from that point)
3. `\drawcard[key=value,...]` (runtime, convenient per page/card)
4. command-style setters `\set...{...}` (one setter per option)
Note: direct commands like `\paperwidth{...}` or `\color{...}` would clash with core LaTeX commands/lengths, therefore the command API uses `\set...{...}` names.
```latex
\documentclass[textwidth=0.7,qrwidth=0.25,www,nofill,iconright,rightalign,hint,icon,textfirst]{businesscard-qrcode}
```
```latex
% runtime/global
\cardsetup{textfirst,noicon,qrwidth=0.35}
% per card/page
\drawcard[noqr,noheader,layout=centered]
% command-style
\setqrwidth{0.35}
\seticon{false}
\setlayout{centered}
```
### Paper and Geometry
- `paperwidth=`: physical paper width, default `89mm`
- `paperheight=`: physical paper height, default `59mm`
- `contentwidth=`: inner content width, default `85mm`
- `contentheight=`: inner content height, default `55mm`
- `padding=`: inner padding, default `2mm`
- `cutdist=`: crop-mark distance, default `2`
- `cutlen=`: crop-mark length, default `1`
- `cutmarks` / `nocutmarks`: enable/disable cut marks, default `cutmarks`
- `nocutmark`: alias for `nocutmarks`
### Typography and Layout
- `fontsize=`: one of `8pt,9pt,10pt,11pt,12pt,14pt,17pt,20pt`, default `8pt`
- `textwidth=`: relative text block width, default `0.50`
- `qrwidth=`: relative QR block width, default `0.40`
- `qrfirst` / `textfirst`: QR left/right order, default `qrfirst`
- `header` / `noheader`: show/hide top name block + separator line, default `header`
- `qr` / `noqr`: show/hide QR block, default `qr`
- `layout=`: `standard` (default) or `centered`
- `headeremphasis=`: `person` (default), `company`, or `balanced`
- `rightalign` / `leftalign`: text alignment, default `rightalign`
- `iconleft` / `iconright`: icon side, default `iconleft`
- `fill` / `nofill`: fill space between icon and text, default `fill`
### Address, Links, and Formatting
- `address` / `noaddress`: include address in print + vCard, default `address`
- `hint` / `nohint`: show small protocol hints, default `hint`
- `icon` / `noicon`: show icons, default `icon`
- `https` / `www`: hint URL style, default `https`
- `lang=`: wikipedia language prefix, default `de`
- `countryformat=`: `auto` (default), `inline`, or `below`
- `crlf` / `nocrlf`: vCard newline style, default `crlf`
- `vcardversion=`: vCard version string, default `4.0`
### Colors and QR Tuning
- `color=`: global text color, default `black`
- `qrcolor=`: QR module color, default `black`
- `qreclevel=`: `L`, `M`, `Q`, `H`, default `H`
- `qrlogoscale=`: QR-center logo size fraction, default `0.25`
- `qrlogoborder=`: QR-center logo padding fraction, default `0.02`
- `qrbgopacity=`: QR white background opacity, default `1.0`
### Logo and Background
- `logoheight=`: default logo height near name (with unit). Auto-default: `4em` if company exists, else `2em`
- `background=`: default background file-or-color at class/runtime option level (equivalent target as `\background{...}`)
- `bgscale=`: background image scale, default `1.0`
- `bgopacity=`: background image opacity, default `1.0`
Standard Layout Blueprint (Normalfall)
======================================
The diagram below shows the default `layout=standard` with `header=true` and `qr=true`
(`qrfirst` variant: QR on the left, text on the right):
![Standard layout blueprint](screenshots/layout-standard.svg)
What Influences What (Standard Layout)
--------------------------------------
- `paperwidth/paperheight/contentwidth/contentheight/padding`: define the outer geometry of the whole card.
- `header/noheader`: enables/disables the complete top block (name/logo/company line + separator line).
- `headeremphasis=person|company|balanced`: controls relative visual weight in the header (`person`: name larger, `company`: company line larger, `balanced`: same size).
- `logo` + `logoheight`: affects header composition and reserved vertical space.
- `company[height=...]` / `companylogo[height=...]`: affects second header line and reserved space.
- `textwidth` and `qrwidth`: define horizontal split of body columns.
- `qr/noqr`: removes the QR column; text then uses full body width.
- `qrfirst/textfirst`: swaps left/right order of QR and text columns.
- `icon/noicon`, `hint/nohint`, `iconleft/iconright`, `fill/nofill`: only affect formatting inside text lines.
- address field presence/visibility: controls whether address block (and map-pin icon) is rendered.
- `pgpfingerprint`: adds an extra footer line and reserves additional vertical space.
- `background`/`bgscale`/`bgopacity`: visual background only, no content reflow.
- `qrlogo`/`qreclevel`/`qrlogoscale`/`qrlogoborder`: QR internals only, no column reflow.
Data Definitions
================
Define data via commands like:
```latex
\email{name@example.com}
```
All data commands support optional `[hide]` (or `[hide=true]`): value remains in QR/vCard but is hidden in printed text.
```latex
\email[hide]{secret@example.com}
```
Recognized Commands
===================
### Name and Identity
- `\type`: `home` or `work` (used in ADR/TEL/EMAIL vCard typing)
- `\honoricprefix`: name prefix/title
- `\givennames`: given names
- `\additionalnames`: additional/middle names
- `\familynames`: family names
- `\honoricsuffix`: name suffix
- `\title`: position/job title (also contributes to displayed/vCard full name)
- `\role`: role/function
- `\company[logo=...,height=...,hide]`: company text with optional inline logo configuration
### Address
- `\pobox`
- `\extaddr`
- `\street`
- `\city`
- `\region`
- `\zip`
- `\country`
### Contact
- `\phone`
- `\email`
- `\jabber`
- `\matrixorg`
- `\cloud`
### Web and Social
- `\homepage`
- `\world`
- `\link`
- `\wordpress`
- `\drupal`
- `\joomla`
- `\wikipedia`
- `\git`
- `\gitea`
- `\github`
- `\facebook`
- `\twitter`
- `\youtube`
- `\google`
### Crypto
- `\pgpurl`
- `\pgpfingerprint`
### Visual Content
- `\logo[height=...]{content}`: logo near name (file path or TeX content)
- `\qrlogo[scale=...,opacity=...]{content}`: logo in QR center (file path or TeX content)
- `\background[scale=...,opacity=...]{file-or-color}`: background image or color
- `\centercontent{...}`: custom content used by `layout=centered`
- `\companylogo[height=...]{content}`: backward-compatible company logo helper
### Multi-Page and State Control
- `\clearfield{<name>}`: remove one field (printed + QR/vCard)
- `\clearcard`: remove all card fields plus card-scoped visuals (`\title`, logo, QR logo, background)
- `\clear{<name>}`: alias of `\clearfield{<name>}` (when no other package already defines `\clear`)
- `\newcard`: alias of `\newpage` + `\clearcard`
- empty structured entries are omitted automatically: if no personal-name parts remain, `N`/`FN` are not emitted; if no address parts remain, `ADR` is not emitted and the address icon/text block is hidden
- `\cardsetup{key=value,...}`: set layout options at runtime
- `\drawcard[key=value,...]`: draw a card and optionally adjust layout options inline
- `\setoption{key}{value}`: generic runtime setter
### Command-Style Setters for Layout Options
- geometry: `\setpaperwidth`, `\setpaperheight`, `\setcontentwidth`, `\setcontentheight`, `\setpadding`, `\setcutdist`, `\setcutlen`
- layout/typography: `\setfontsize`, `\settextwidth`, `\setqrwidth`, `\setqreclevel`, `\setqrlogoscale`, `\setqrlogoborder`, `\setlogoheight`, `\setlayout`, `\setheaderemphasis`
- booleans (`true`/`false`): `\setcrlf`, `\setaddress`, `\sethint`, `\seticon`, `\setrightalign`, `\seticonleft`, `\setfill`, `\setqrfirst`, `\setheader`, `\setqr`, `\sethttps`, `\setcutmarks`
- colors/language/format: `\setlang`, `\setcardcolor`, `\setqrcolor`, `\setcountryformat`, `\setbackground`, `\setbgscale`, `\setbgopacity`, `\setqrbgopacity`, `\setvcardversion`
- convenience toggles: `\noheader`, `\withheader`, `\noqr`, `\withqr`, `\nocutmarks`, `\withcutmarks`, `\standardlayout`, `\centeredlayout`
### Document Title Interop
- `\title{...}` is repurposed by this class for card position/title content
- `\carddocumenttitle{...}` calls the original LaTeX document-title command if needed
Second Page (Front/Back)
========================
Use one source file for front/back variants:
```latex
\begin{document}
% Page 1
\type{home}
\givennames{John}
\familynames{Doe}
\email{name@example.com}
\drawcard
% Page 2
\newcard
\type{work}
\company{My\ Company\ LTD}
\title{CEO}
\email{doe@mycompany.ltd}
\drawcard
\end{document}
```
Alternative: centered back side without QR and without header:
```latex
\newcard
\centercontent{{\Large\bfseries My\ Company\ LTD}\par\vspace{0.8em}hello@mycompany.ltd\par mycompany.ltd}
\drawcard[layout=centered,noqr,noheader]
```
Complete working example: [centered-backside-example.tex](examples/centered-backside-example.tex)
Equivalent using setter commands:
```latex
\newcard
\setlayout{centered}
\setqr{false}
\setheader{false}
\centercontent{{\Large\bfseries My\ Company\ LTD}\par\vspace{0.8em}hello@mycompany.ltd\par mycompany.ltd}
\drawcard
```
Header emphasis example:
```latex
\cardsetup{headeremphasis=company}
% or:
\setheaderemphasis{company}
% optional short alias:
\headeremphasis{balanced}
```
If you want to keep most data and only remove selected fields:
```latex
\newpage
\clear{givennames}
\clear{familynames}
\drawcard
```
See [john-doe-hongkong.tex](examples/john-doe-hongkong.tex) for a full two-page example.
Logo and Background Examples
============================
### Logo next to name
```latex
\documentclass{businesscard-qrcode}
\logo{logo.png}
```
### Logo in QR center
```latex
\documentclass[qreclevel=H,qrlogoscale=0.25]{businesscard-qrcode}
\qrlogo[scale=0.25]{logo.png}
```
Important for QR-center logos:
- prefer `qreclevel=H`
- test scan quality with multiple apps/devices
- reduce `qrlogoscale` if decoding becomes unreliable
### Large logo next to name
```latex
\documentclass[logoheight=6em]{businesscard-qrcode}
\logo{logo.png}
```
### Background color
```latex
\documentclass{businesscard-qrcode}
\background{yellow!20}
```
### Background image
```latex
\documentclass[bgscale=1.5,bgopacity=0.3,qrbgopacity=1.0]{businesscard-qrcode}
\background{photo.png}
```
Print the Card
==============
The default print format is `89mm × 59mm` with `2mm` border/cut distance (inner card: `85mm × 55mm`).
Example for `10cm × 5cm` card with `2mm` cut:
```latex
\documentclass[paperheight=5.4cm,paperwidth=10.4cm,
contentheight=5cm,contentwidth=10cm,
cutdist=2]{businesscard-qrcode}
```
![example with special paper size](screenshots/special-papersize.png)
Before printing, validate QR readability (phone app + command line, e.g. `zbarimg businesscard.pdf`).
Need More Need More
========= =========
If you are missing a feature or a configuration option, consult the [project] page. Just open a [ticket] and the [author] will care about it. Or extend it, it's [lgpl]. If you are missing a feature or configuration option, consult [project] and open a [ticket]. Contributions are welcome ([lgpl]).
[examples]: examples "more examples" [examples]: examples "more examples"
@@ -230,3 +485,5 @@ If you are missing a feature or a configuration option, consult the [project] pa
[author]: https://marc.wäckerlin.ch "Marc Wäckerlin" [author]: https://marc.wäckerlin.ch "Marc Wäckerlin"
[project]: https://mrw.sh/templates/businesscard-qrcode "the main project page" [project]: https://mrw.sh/templates/businesscard-qrcode "the main project page"
[lgpl]: https://www.gnu.org/licenses/lgpl-3.0 "Library GNU Public License" [lgpl]: https://www.gnu.org/licenses/lgpl-3.0 "Library GNU Public License"
Fossify Contacts bug report: https://github.com/FossifyOrg/Contacts/issues/548
+959 -143
View File
@@ -7,9 +7,10 @@
% option evaluation % option evaluation
\RequirePackage{kvoptions} \RequirePackage{kvoptions}
\SetupKeyvalOptions{ \SetupKeyvalOptions{
family=BCQ, family=BCQ,
prefix=BCQ@ prefix=BCQ@
} }
% Paper/content geometry
\DeclareStringOption[89mm]{paperwidth} \DeclareStringOption[89mm]{paperwidth}
\DeclareStringOption[59mm]{paperheight} \DeclareStringOption[59mm]{paperheight}
\DeclareStringOption[85mm]{contentwidth} \DeclareStringOption[85mm]{contentwidth}
@@ -20,7 +21,22 @@
\DeclareStringOption[1]{cutlen} \DeclareStringOption[1]{cutlen}
\DeclareStringOption[0.50]{textwidth} \DeclareStringOption[0.50]{textwidth}
\DeclareStringOption[0.40]{qrwidth} \DeclareStringOption[0.40]{qrwidth}
% QR rendering
\DeclareStringOption[H]{qreclevel} % QR code error correction level (L,M,Q,H)
\DeclareStringOption[0.25]{qrlogoscale} % logo size in QR code as fraction of QR width (1.0 = 100%), default 0.25
\DeclareStringOption[0.02]{qrlogoborder} % white padding around logo in QR as fraction of QR width (1.0 = 100%), default 0.02
% Header/background
\DeclareStringOption{logoheight} % logo height next to name (with unit, e.g., 4em), default: 4em if company set, 2em otherwise
\DeclareStringOption[1.0]{bgscale} % background image scale (1.0 = 100% card height), default 1.0
\DeclareStringOption[1.0]{bgopacity} % background image opacity (1.0 = 100% visible, 0.0 = invisible), default 1.0
\DeclareStringOption[1.0]{qrbgopacity} % QR code background opacity (1.0 = white solid, 0.0 = transparent), default 1.0
\DeclareStringOption[]{background} % default background (file or color), equivalent to \background{...}
% Formatting/content behavior
\DeclareStringOption[de]{lang} \DeclareStringOption[de]{lang}
\DeclareStringOption[black]{color}
\DeclareStringOption[black]{qrcolor}
\DeclareBoolOption[true]{crlf} % use CRLF line endings in vCard (iOS compatibility)
\DeclareComplementaryOption{nocrlf}{crlf}
\DeclareBoolOption[true]{address} \DeclareBoolOption[true]{address}
\DeclareComplementaryOption{noaddress}{address} \DeclareComplementaryOption{noaddress}{address}
\DeclareBoolOption[true]{hint} \DeclareBoolOption[true]{hint}
@@ -35,8 +51,19 @@
\DeclareComplementaryOption{nofill}{fill} \DeclareComplementaryOption{nofill}{fill}
\DeclareBoolOption[true]{qrfirst} \DeclareBoolOption[true]{qrfirst}
\DeclareComplementaryOption{textfirst}{qrfirst} \DeclareComplementaryOption{textfirst}{qrfirst}
\DeclareBoolOption[true]{header}
\DeclareComplementaryOption{noheader}{header}
\DeclareBoolOption[true]{qr}
\DeclareComplementaryOption{noqr}{qr}
\DeclareBoolOption[true]{https} \DeclareBoolOption[true]{https}
\DeclareComplementaryOption{www}{https} \DeclareComplementaryOption{www}{https}
\DeclareBoolOption[true]{cutmarks}
\DeclareComplementaryOption{nocutmark}{cutmarks}
\DeclareComplementaryOption{nocutmarks}{cutmarks}
\DeclareStringOption[standard]{layout} % standard, centered
\DeclareStringOption[auto]{countryformat} % auto: <4 chars inline with mdash, >=4 separate line; inline: always inline; below: always separate line
\DeclareStringOption[person]{headeremphasis} % person, company, balanced
\DeclareStringOption[4.0]{vcardversion} % default 4.0 (current behavior), optional 3.0 for compatibility
\DeclareDefaultOption{\@unknownoptionerror} \DeclareDefaultOption{\@unknownoptionerror}
\ProcessKeyvalOptions* \ProcessKeyvalOptions*
@@ -54,6 +81,7 @@
\def\protdisplay{\ifBCQ@https https://\else www.\fi} \def\protdisplay{\ifBCQ@https https://\else www.\fi}
\def\protprefix{\ifBCQ@https https://\fi} \def\protprefix{\ifBCQ@https https://\fi}
\ifBCQ@address\def\printaddress{}\fi \ifBCQ@address\def\printaddress{}\fi
\ifx\BCQ@background\@empty\else\def\Xbackground{\BCQ@background}\fi
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -62,10 +90,17 @@
\RequirePackage{marvosym} \RequirePackage{marvosym}
\RequirePackage{fontawesome} \RequirePackage{fontawesome}
\RequirePackage[final]{qrcode} \RequirePackage[final]{qrcode}
\RequirePackage{xcolor}
\RequirePackage{etoolbox} \RequirePackage{etoolbox}
\RequirePackage{xstring} % for string length checking
\RequirePackage{DejaVuSans} \RequirePackage{DejaVuSans}
\RequirePackage[T1]{fontenc} \RequirePackage[T1]{fontenc}
\RequirePackage{wrapfig} \RequirePackage{wrapfig}
\RequirePackage{graphicx} % needed for optional logo
\RequirePackage{tikz} % needed for logo overlay in QR code
\RequirePackage{eso-pic} % needed for background images without layout impact
% Fix XeLaTeX opacity issue: ensure TikZ/PGF is loaded before eso-pic uses opacity
\DeclareHookRule{shipout/background}{pgfrcs}{>}{eso-pic}
\RequirePackage[\content,top=\padding,left=\padding,right=\padding,bottom=\padding]{geometry} \RequirePackage[\content,top=\padding,left=\padding,right=\padding,bottom=\padding]{geometry}
%\RequirePackage{pbox} %\RequirePackage{pbox}
\RequirePackage{varwidth} \RequirePackage{varwidth}
@@ -74,22 +109,239 @@
\setlength{\parindent}{0pt} \setlength{\parindent}{0pt}
\renewcommand*\familydefault{\sfdefault} \renewcommand*\familydefault{\sfdefault}
\setlength{\fboxsep}{0pt} \setlength{\fboxsep}{0pt}
\color{\BCQ@color}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% data registration % data registration
\newcommand\registerData[1]{ \newcommand\BCQ@datareset{%
\expandafter\newcommand\csname #1\endcsname[1]{ \def\BCQ@data@hide{}%
\expandafter\def\csname X#1\endcsname{##1} \def\BCQ@data@logo{}%
} \def\BCQ@data@height{}%
}
\newcommand\BCQ@setbool[2]{%
\edef\BCQ@booltmp{#2}%
\ifdefstring{\BCQ@booltmp}{false}{%
\csname BCQ@#1false\endcsname
}{%
\csname BCQ@#1true\endcsname
}%
}
% Runtime configuration keys (usable via \cardsetup and \drawcard[...])
% Geometry / dimensions
\define@key{BCQ@runtime}{paperwidth}{\def\BCQ@paperwidth{#1}}
\define@key{BCQ@runtime}{paperheight}{\def\BCQ@paperheight{#1}}
\define@key{BCQ@runtime}{contentwidth}{%
\def\BCQ@contentwidth{#1}%
\def\content{paperwidth=\BCQ@contentwidth,paperheight=\BCQ@contentheight}%
}
\define@key{BCQ@runtime}{contentheight}{%
\def\BCQ@contentheight{#1}%
\def\content{paperwidth=\BCQ@contentwidth,paperheight=\BCQ@contentheight}%
}
\define@key{BCQ@runtime}{fontsize}{\def\BCQ@fontsize{#1}}
\define@key{BCQ@runtime}{padding}{\def\BCQ@padding{#1}\def\padding{\BCQ@padding}}
\define@key{BCQ@runtime}{cutdist}{\def\BCQ@cutdist{#1}\def\border{\BCQ@cutdist}}
\define@key{BCQ@runtime}{cutlen}{\def\BCQ@cutlen{#1}\def\cutlen{\BCQ@cutlen}}
\define@key{BCQ@runtime}{textwidth}{\def\BCQ@textwidth{#1}\def\textpercents{\BCQ@textwidth}}
\define@key{BCQ@runtime}{qrwidth}{\def\BCQ@qrwidth{#1}\def\imagepercents{\BCQ@qrwidth}}
% QR / background / visuals
\define@key{BCQ@runtime}{qreclevel}{\def\BCQ@qreclevel{#1}}
\define@key{BCQ@runtime}{qrlogoscale}{\def\BCQ@qrlogoscale{#1}}
\define@key{BCQ@runtime}{qrlogoborder}{\def\BCQ@qrlogoborder{#1}}
\define@key{BCQ@runtime}{logoheight}{\def\BCQ@logoheight{#1}}
\define@key{BCQ@runtime}{bgscale}{\def\BCQ@bgscale{#1}}
\define@key{BCQ@runtime}{bgopacity}{\def\BCQ@bgopacity{#1}}
\define@key{BCQ@runtime}{qrbgopacity}{\def\BCQ@qrbgopacity{#1}}
\define@key{BCQ@runtime}{lang}{\def\BCQ@lang{#1}\def\lang{\BCQ@lang}}
\define@key{BCQ@runtime}{color}{\def\BCQ@color{#1}\color{\BCQ@color}}
\define@key{BCQ@runtime}{qrcolor}{\def\BCQ@qrcolor{#1}}
\define@key{BCQ@runtime}{countryformat}{\def\BCQ@countryformat{#1}}
\define@key{BCQ@runtime}{layout}{\def\BCQ@layout{#1}}
\define@key{BCQ@runtime}{headeremphasis}{\def\BCQ@headeremphasis{#1}}
\define@key{BCQ@runtime}{vcardversion}{\def\BCQ@vcardversion{#1}}
% Boolean toggles
\define@key{BCQ@runtime}{crlf}[true]{\BCQ@setbool{crlf}{#1}}
\define@key{BCQ@runtime}{nocrlf}[true]{\BCQ@setbool{crlf}{false}}
\define@key{BCQ@runtime}{address}[true]{%
\BCQ@setbool{address}{#1}%
\ifBCQ@address
\def\printaddress{}%
\else
\csundef{printaddress}%
\fi
}
\define@key{BCQ@runtime}{noaddress}[true]{\BCQ@setbool{address}{false}\csundef{printaddress}}
\define@key{BCQ@runtime}{hint}[true]{\BCQ@setbool{hint}{#1}}
\define@key{BCQ@runtime}{nohint}[true]{\BCQ@setbool{hint}{false}}
\define@key{BCQ@runtime}{icon}[true]{\BCQ@setbool{icon}{#1}}
\define@key{BCQ@runtime}{noicon}[true]{\BCQ@setbool{icon}{false}}
\define@key{BCQ@runtime}{rightalign}[true]{\BCQ@setbool{rightalign}{#1}}
\define@key{BCQ@runtime}{leftalign}[true]{\BCQ@setbool{rightalign}{false}}
\define@key{BCQ@runtime}{iconleft}[true]{\BCQ@setbool{iconleft}{#1}}
\define@key{BCQ@runtime}{iconright}[true]{\BCQ@setbool{iconleft}{false}}
\define@key{BCQ@runtime}{fill}[true]{\BCQ@setbool{fill}{#1}}
\define@key{BCQ@runtime}{nofill}[true]{\BCQ@setbool{fill}{false}}
\define@key{BCQ@runtime}{qrfirst}[true]{\BCQ@setbool{qrfirst}{#1}}
\define@key{BCQ@runtime}{textfirst}[true]{\BCQ@setbool{qrfirst}{false}}
\define@key{BCQ@runtime}{header}[true]{\BCQ@setbool{header}{#1}}
\define@key{BCQ@runtime}{noheader}[true]{\BCQ@setbool{header}{false}}
\define@key{BCQ@runtime}{qr}[true]{\BCQ@setbool{qr}{#1}}
\define@key{BCQ@runtime}{noqr}[true]{\BCQ@setbool{qr}{false}}
\define@key{BCQ@runtime}{https}[true]{\BCQ@setbool{https}{#1}}
\define@key{BCQ@runtime}{www}[true]{\BCQ@setbool{https}{false}}
\define@key{BCQ@runtime}{background}{\def\Xbackground{#1}}
\define@key{BCQ@runtime}{cutmarks}[true]{\BCQ@setbool{cutmarks}{#1}}
\define@key{BCQ@runtime}{nocutmark}[true]{\BCQ@setbool{cutmarks}{false}}
\define@key{BCQ@runtime}{nocutmarks}[true]{\BCQ@setbool{cutmarks}{false}}
\newcommand\cardsetup[1]{\setkeys{BCQ@runtime}{#1}}
\newcommand\setoption[2]{\setkeys{BCQ@runtime}{#1=#2}}
% Command-style setters for all layout/runtime options
\newcommand\setpaperwidth[1]{\setoption{paperwidth}{#1}}
\newcommand\setpaperheight[1]{\setoption{paperheight}{#1}}
\newcommand\setcontentwidth[1]{\setoption{contentwidth}{#1}}
\newcommand\setcontentheight[1]{\setoption{contentheight}{#1}}
\newcommand\setfontsize[1]{\setoption{fontsize}{#1}}
\newcommand\setpadding[1]{\setoption{padding}{#1}}
\newcommand\setcutdist[1]{\setoption{cutdist}{#1}}
\newcommand\setcutlen[1]{\setoption{cutlen}{#1}}
\newcommand\settextwidth[1]{\setoption{textwidth}{#1}}
\newcommand\setqrwidth[1]{\setoption{qrwidth}{#1}}
\newcommand\setqreclevel[1]{\setoption{qreclevel}{#1}}
\newcommand\setqrlogoscale[1]{\setoption{qrlogoscale}{#1}}
\newcommand\setqrlogoborder[1]{\setoption{qrlogoborder}{#1}}
\newcommand\setlogoheight[1]{\setoption{logoheight}{#1}}
\newcommand\setbgscale[1]{\setoption{bgscale}{#1}}
\newcommand\setbgopacity[1]{\setoption{bgopacity}{#1}}
\newcommand\setqrbgopacity[1]{\setoption{qrbgopacity}{#1}}
\newcommand\setlang[1]{\setoption{lang}{#1}}
\newcommand\setcardcolor[1]{\setoption{color}{#1}}
\newcommand\setqrcolor[1]{\setoption{qrcolor}{#1}}
\newcommand\setcountryformat[1]{\setoption{countryformat}{#1}}
\newcommand\setlayout[1]{\setoption{layout}{#1}}
\newcommand\setheaderemphasis[1]{\setoption{headeremphasis}{#1}}
\newcommand\headeremphasis[1]{\setoption{headeremphasis}{#1}}
\newcommand\setvcardversion[1]{\setoption{vcardversion}{#1}}
\newcommand\setcrlf[1]{\setoption{crlf}{#1}}
\newcommand\setaddress[1]{\setoption{address}{#1}}
\newcommand\sethint[1]{\setoption{hint}{#1}}
\newcommand\seticon[1]{\setoption{icon}{#1}}
\newcommand\setrightalign[1]{\setoption{rightalign}{#1}}
\newcommand\seticonleft[1]{\setoption{iconleft}{#1}}
\newcommand\setfill[1]{\setoption{fill}{#1}}
\newcommand\setqrfirst[1]{\setoption{qrfirst}{#1}}
\newcommand\setheader[1]{\setoption{header}{#1}}
\newcommand\setqr[1]{\setoption{qr}{#1}}
\newcommand\sethttps[1]{\setoption{https}{#1}}
\newcommand\setbackground[1]{\setoption{background}{#1}}
\newcommand\setcutmarks[1]{\setoption{cutmarks}{#1}}
% convenience toggles
\newcommand\noheader{\cardsetup{noheader}}
\newcommand\withheader{\cardsetup{header}}
\newcommand\noqr{\cardsetup{noqr}}
\newcommand\withqr{\cardsetup{qr}}
\newcommand\nocutmarks{\cardsetup{nocutmarks}}
\newcommand\withcutmarks{\cardsetup{cutmarks}}
\newcommand\standardlayout{\cardsetup{layout=standard}}
\newcommand\centeredlayout{\cardsetup{layout=centered}}
\def\BCQ@registeredfields{}
\newcommand\BCQ@registerfieldname[1]{%
\ifx\BCQ@registeredfields\@empty
\xdef\BCQ@registeredfields{#1}%
\else
\xdef\BCQ@registeredfields{\BCQ@registeredfields,#1}%
\fi
}
\newcommand\BCQ@clearfieldinternal[1]{%
\csundef{X#1}%
\csundef{X#1@hide}%
}
\newcommand\clearfield[1]{%
\BCQ@clearfieldinternal{#1}%
\ifstrequal{#1}{company}{%
\csundef{Xcompanylogo}%
\csundef{Xcompanylogoheight}%
\setlength{\BCQ@companybrandingheight}{2em}%
}{}%
\global\let\BCQ@cachedname\@empty
}
\newcommand\clearcard{%
\@for\BCQ@field:=\BCQ@registeredfields\do{%
\expandafter\BCQ@clearfieldinternal\expandafter{\BCQ@field}%
}%
\clearfield{title}%
\csundef{Xlogo}%
\csundef{BCQ@logoheight@local}%
\csundef{Xqrlogo}%
\csundef{BCQ@qrlogoscale@local}%
\csundef{BCQ@qrbgopacity@local}%
\csundef{Xbackground}%
\csundef{BCQ@bgscale@local}%
\csundef{BCQ@bgopacity@local}%
\csundef{Xcompanylogo}%
\csundef{Xcompanylogoheight}%
\setlength{\BCQ@companybrandingheight}{2em}%
\global\let\BCQ@cachedname\@empty
}
% Convenience aliases for multi-page workflows:
% \clear{field} -> \clearfield{field}
% \newcard -> \newpage + \clearcard
\providecommand\clear[1]{\clearfield{#1}}
\providecommand\newcard{\newpage\clearcard}
\define@key{BCQ@data}{hide}[true]{%
\edef\BCQ@data@hide{#1}%
}
\define@key{BCQ@data}{logo}{%
\def\BCQ@data@logo{#1}%
}
\define@key{BCQ@data}{height}{%
\def\BCQ@data@height{#1}%
}
\newlength{\BCQ@companybrandingheight}
\setlength{\BCQ@companybrandingheight}{2em}
\newcommand\BCQ@applycompanyoptions{%
\csundef{Xcompanylogo}%
\csundef{Xcompanylogoheight}%
\setlength{\BCQ@companybrandingheight}{2em}%
\ifx\BCQ@data@logo\@empty\else
\let\Xcompanylogo\BCQ@data@logo
\ifx\BCQ@data@height\@empty
\def\Xcompanylogoheight{1.5em}%
\else
\edef\Xcompanylogoheight{\BCQ@data@height}%
\fi
\setlength{\BCQ@companybrandingheight}{\Xcompanylogoheight}%
\fi
}
\newcommand\registerData[1]{%
\BCQ@registerfieldname{#1}%
\expandafter\newcommand\csname #1\endcsname[2][]{%
\BCQ@datareset
\edef\BCQ@data@options{##1}%
\ifx\BCQ@data@options\@empty\else
\setkeys{BCQ@data}{##1}%
\fi
\csundef{X#1@hide}%
\ifx\BCQ@data@hide\@empty\else
\edef\BCQ@data@hidetmp{\BCQ@data@hide}%
\ifdefstring{\BCQ@data@hidetmp}{false}{}{%
\expandafter\def\csname X#1@hide\endcsname{true}%
}%
\fi
\expandafter\def\csname X#1\endcsname{##2}%
\ifstrequal{#1}{company}{\BCQ@applycompanyoptions}{}%
}%
} }
\registerData{type} \registerData{type}
\registerData{givennames} \registerData{givennames}
\registerData{familynames} \registerData{familynames}
\registerData{honoricprefix} \registerData{honoricprefix}
\registerData{honoricsuffix} \registerData{honoricsuffix}
\registerData{company}
\registerData{additionalnames} \registerData{additionalnames}
\registerData{pobox} \registerData{pobox}
\registerData{role}
\registerData{extaddr} \registerData{extaddr}
\registerData{street} \registerData{street}
\registerData{city} \registerData{city}
@@ -118,123 +370,582 @@
\registerData{pgpurl} \registerData{pgpurl}
\registerData{pgpfingerprint} \registerData{pgpfingerprint}
% Override document \title to capture card title (original available via \carddocumenttitle)
\let\BCQ@documenttitle\title
\renewcommand\title[1]{%
\def\Xtitle{#1}%
}
\newcommand\carddocumenttitle[1]{%
\BCQ@documenttitle{#1}%
}
% Special commands with optional parameters
% \logo[height=...]{file} - logo next to name, overrides logoheight option
\define@key{BCQ@logo}{height}{\def\BCQ@logoheight@local{#1}}
\newcommand\logo[2][]{
\def\Xlogo{#2}
\def\BCQ@logo@tmp{#1}%
\ifx\BCQ@logo@tmp\@empty\else
\setkeys{BCQ@logo}{#1}
\fi
}
% \qrlogo[scale=...,opacity=...]{file} - logo in QR code center (scale is unitless fraction like 0.3)
\define@key{BCQ@qrlogo}{scale}{\def\BCQ@qrlogoscale@local{#1}}
\define@key{BCQ@qrlogo}{opacity}{\def\BCQ@qrbgopacity@local{#1}}
\newcommand\qrlogo[2][]{
\def\Xqrlogo{#2}
\def\BCQ@qrlogo@tmp{#1}%
\ifx\BCQ@qrlogo@tmp\@empty\else
\setkeys{BCQ@qrlogo}{#1}
\fi
}
% \background[scale=...,opacity=...]{file/color} - background image or color
\define@key{BCQ@background}{scale}{\def\BCQ@bgscale@local{#1}}
\define@key{BCQ@background}{opacity}{\def\BCQ@bgopacity@local{#1}}
\newcommand\background[2][]{
\def\Xbackground{#2}
\def\BCQ@background@tmp{#1}%
\ifx\BCQ@background@tmp\@empty\else
\setkeys{BCQ@background}{#1}
\fi
}
\newcommand\centercontent[1]{%
\def\Xcentercontent{#1}%
}
\registerData{companylogo} % content (image/object) to display instead of company text (company still in vCard)
\define@key{BCQ@companylogo}{height}{%
\def\BCQ@companylogo@height{#1}%
}
\renewcommand\companylogo[2][]{%
\def\BCQ@companylogo@height{}%
\edef\BCQ@companylogo@options{#1}%
\ifx\BCQ@companylogo@options\@empty\else
\setkeys{BCQ@companylogo}{#1}%
\fi
\def\Xcompanylogo{#2}%
\ifx\BCQ@companylogo@height\@empty
\def\Xcompanylogoheight{1.5em}%
\else
\edef\Xcompanylogoheight{\BCQ@companylogo@height}%
\fi
\setlength{\BCQ@companybrandingheight}{\Xcompanylogoheight}%
}
\newcommand\ifvisible[3]{%
\ifcsdef{#1}{%
\ifcsdef{#1@hide}{#3}{#2}%
}{#3}%
}
\newcommand\conddisplay[1]{%
\ifvisible{#1}{\exec{#1}}{}%
}
\newcommand\BCQ@resolveusedoption[3]{%
\ifcsdef{#1}{%
\edef#3{\csname #1\endcsname}%
}{%
\edef#3{#2}%
}%
}
\newcommand\BCQ@insertcompanyline{%
\ifhaspersonalname{%
\ifhaspositionblock{\\[0.7ex]\BCQ@headercompanyformat{\companybrandingline}}{}%
}{}%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% auxiliary commands % auxiliary commands
\newcommand\enforceright{\leftskip0pt plus 1fill\rightskip0pt} \newcommand\enforceright{\leftskip0pt plus 1fill\rightskip0pt}
\newcommand\exec[1]{\csname #1\endcsname} \newcommand\exec[1]{\csname #1\endcsname}
\newcommand\insa[3][]{\ifcsdef{#2}{ \newcommand\insa[3][]{\ifvisible{#2}{
\ifBCQ@iconleft \ifBCQ@iconleft
\ifBCQ@icon\parbox{1em}{\centering\exec{#3}}\ \fi\ifBCQ@hint{\tiny#1}\fi\ifBCQ@fill\hfill\fi\exec{#2} \ifBCQ@icon\parbox{1em}{\centering\exec{#3}}\ \fi\ifBCQ@hint{\tiny#1}\fi\ifBCQ@fill\hfill\fi\exec{#2}
\else \else
\ifBCQ@hint{\tiny#1\ }\fi\exec{#2}\ifBCQ@fill\hfill\fi\ifBCQ@icon\ \parbox{1em}{\centering\exec{#3}}\fi \ifBCQ@hint{\tiny#1\ }\fi\exec{#2}\ifBCQ@fill\hfill\fi\ifBCQ@icon\ \parbox{1em}{\centering\exec{#3}}\fi
\fi \fi
}{}} }{}}
\newcommand\ifexists[2]{\ifcsdef{#1}{#2}{}} \newcommand\ifexists[2]{\ifcsdef{#1}{#2}{}}
\newcommand\ifboth[3]{\ifcsdef{#1}{\ifcsdef{#2}{#3}{}}{}} \newcommand\ifboth[3]{\ifcsdef{#1}{\ifcsdef{#2}{#3}{}}{}}
\newcommand\ifany[3]{\ifcsdef{#1}{#3}{\ifcsdef{#2}{#3}{}}} \newcommand\ifany[3]{\ifcsdef{#1}{#3}{\ifcsdef{#2}{#3}{}}}
\newcommand\cond[1]{\ifcsdef{#1}{\exec{#1}}{}} \newcommand\cond[1]{\ifcsdef{#1}{\exec{#1}}{}}
\newcommand\heightscale{\dimexpr\textheight-\ifcsempty{name}{0em}{2em}-\ifcsdef{Xpgpfingerprint}{2em}{0em}-\ifcsdef{Xadditionalnames}{2em}{0em}\relax} \newcommand\BCQ@graphiccontent[2]{%
\begingroup
\edef\BCQ@graphicscan{\expandafter\detokenize\expandafter{#1}}%
\IfSubStr{\BCQ@graphicscan}{\string\\}{%
\endgroup #1%
}{%
\xdef\BCQ@graphicspath{\BCQ@graphicscan}%
\endgroup
\IfFileExists{\BCQ@graphicspath}{%
\includegraphics[#2]{\BCQ@graphicspath}%
}{%
#1%
}%
}%
}
% internal boxes and lengths for measuring
\newsavebox{\BCQ@namebox}
\newsavebox{\BCQ@logobox}
\newsavebox{\BCQ@companytitlebox}
\newsavebox{\BCQ@companyrightbox}
\newlength{\BCQ@logoheightdimen}
\setlength{\BCQ@logoheightdimen}{0pt}% initialize to prevent errors
\newlength{\BCQ@bgimagedimen}
\setlength{\BCQ@bgimagedimen}{0pt}
\newdimen\BCQ@companytitlewidth
\newdimen\BCQ@companyrightwidth
\newdimen\BCQ@companylineavailable
\newdimen\BCQ@companylinesum
\newif\ifBCQ@companylineneeded
\newif\ifBCQ@companytitleexists
\newif\ifBCQ@companyrightexists
\newlength{\BCQ@reservedheight}
\newlength{\BCQ@heightscale}
\newlength{\BCQ@namewidth}
\newlength{\BCQ@namecolumnwidth}
\newlength{\BCQ@logosep}
\newlength{\BCQ@logosepused}
\setlength{\BCQ@logosep}{1em}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% name - assemble full name from the parts, such as Xgivennames and Xfamilynames % name - assemble full name from the parts, such as Xgivennames and Xfamilynames
\newcommand\name{\ifexists{Xhonoricprefix}{\Xhonoricprefix\ }\ifexists{Xgivennames}{\Xgivennames\ }\ifexists{Xfamilynames}{\Xfamilynames}\ifexists{Xhonoricsuffix}{\ \Xhonoricsuffix}} \newcommand\personalnamevcard{%
\ifexists{Xhonoricprefix}{\Xhonoricprefix\ }%
\ifexists{Xgivennames}{\Xgivennames\ }%
\ifexists{Xadditionalnames}{\Xadditionalnames\ }%
\ifexists{Xfamilynames}{\Xfamilynames}%
\ifexists{Xhonoricsuffix}{\ \Xhonoricsuffix}%
}
\newcommand\personalnamefn{%
\ifexists{Xgivennames}{\Xgivennames\ }%
\ifexists{Xadditionalnames}{\Xadditionalnames\ }%
\ifexists{Xfamilynames}{\Xfamilynames}%
}
\newcommand\personalname{%
\ifvisible{Xhonoricprefix}{\Xhonoricprefix\ }{}%
\ifvisible{Xgivennames}{\Xgivennames\ }{}%
\ifvisible{Xadditionalnames}{\Xadditionalnames\ }{}%
\ifvisible{Xfamilynames}{\Xfamilynames}{}%
\ifvisible{Xhonoricsuffix}{\ \Xhonoricsuffix}{}%
}
\newcommand\ifhaspersonalname[2]{%
\ifvisible{Xhonoricprefix}{#1}{%
\ifvisible{Xgivennames}{#1}{%
\ifvisible{Xadditionalnames}{#1}{%
\ifvisible{Xfamilynames}{#1}{%
\ifvisible{Xhonoricsuffix}{#1}{#2}%
}%
}%
}%
}%
}
\newcommand\ifhaspositiontext[2]{%
\ifvisible{Xcompany}{#1}{%
\ifvisible{Xtitle}{#1}{%
\ifvisible{Xrole}{#1}{#2}%
}%
}%
}
\newcommand\ifhaspositionblock[2]{%
\ifhaspositiontext{#1}{%
\ifcsdef{Xcompanylogo}{#1}{#2}%
}%
}
\newcommand\ifhaspersonalnamevcard[2]{%
\ifcsname Xhonoricprefix\endcsname
#1%
\else\ifcsname Xgivennames\endcsname
#1%
\else\ifcsname Xadditionalnames\endcsname
#1%
\else\ifcsname Xfamilynames\endcsname
#1%
\else\ifcsname Xhonoricsuffix\endcsname
#1%
\else
#2%
\fi\fi\fi\fi\fi
}
\newcommand\ifhasaddressvcard[2]{%
\ifcsname Xpobox\endcsname
#1%
\else\ifcsname Xextaddr\endcsname
#1%
\else\ifcsname Xstreet\endcsname
#1%
\else\ifcsname Xcity\endcsname
#1%
\else\ifcsname Xregion\endcsname
#1%
\else\ifcsname Xzip\endcsname
#1%
\else\ifcsname Xcountry\endcsname
#1%
\else
#2%
\fi\fi\fi\fi\fi\fi\fi
}
\newcommand\ifhasaddressvisible[2]{%
\ifvisible{Xpobox}{#1}{%
\ifvisible{Xextaddr}{#1}{%
\ifvisible{Xstreet}{#1}{%
\ifvisible{Xcity}{#1}{%
\ifvisible{Xregion}{#1}{%
\ifvisible{Xzip}{#1}{%
\ifvisible{Xcountry}{#1}{#2}%
}%
}%
}%
}%
}%
}%
}
\newcommand\ifhasfullnamevcard[2]{%
\ifhaspersonalnamevcard{#1}{%
\ifcsname Xtitle\endcsname
#1%
\else\ifcsname Xrole\endcsname
#1%
\else\ifcsname Xcompany\endcsname
#1%
\else
#2%
\fi\fi\fi
}%
}
% heightscale - calculate available height for text/QR
% Uses actual logo height if logo is taller than default reserved space
% This is computed as a length and stored, not a macro
\newcommand\computeheightscale{%
\ifBCQ@header
\setlength{\BCQ@reservedheight}{\dimexpr
\ifhaspersonalname{2em}{\ifhaspositionblock{0pt}{2em}}%
+\ifhaspositionblock{\BCQ@companybrandingheight}{0pt}\relax}%
\else
\setlength{\BCQ@reservedheight}{0pt}%
\fi
\ifdim\BCQ@logoheightdimen>\BCQ@reservedheight
\setlength{\BCQ@heightscale}{\dimexpr\textheight-\BCQ@logoheightdimen-\ifcsdef{Xpgpfingerprint}{2em}{0em}\relax}%
\else
\setlength{\BCQ@heightscale}{\dimexpr\textheight-\BCQ@reservedheight-\ifcsdef{Xpgpfingerprint}{2em}{0em}\relax}%
\fi
}
\newcommand\heightscale{\BCQ@heightscale}
\newcommand\companytitleblock{%
\ifvisible{Xtitle}{\Xtitle}{}%
\ifvisible{Xrole}{%
\ifvisible{Xtitle}{,\ }{}%
\Xrole
}{}%
}
\newcommand\companyrightblock{%
\ifcsdef{Xcompanylogo}{\companylogocontent}{}%
\ifvisible{Xcompany}{%
\Xcompany
\ifcsdef{Xcompanylogo}{\hspace{0.5em}}{}%
}{}%
}
\newcommand\companybrandingline{%
\begingroup
\BCQ@companytitleexistsfalse
\ifvisible{Xtitle}{\BCQ@companytitleexiststrue}{}%
\ifvisible{Xrole}{\BCQ@companytitleexiststrue}{}%
\BCQ@companyrightexistsfalse
\ifvisible{Xcompany}{\BCQ@companyrightexiststrue}{}%
\ifcsdef{Xcompanylogo}{\BCQ@companyrightexiststrue}{}%
\ifBCQ@companytitleexists
\companytitleblock
\fi
\ifBCQ@companytitleexists
\ifBCQ@companyrightexists
\space
\fi
\fi
\ifBCQ@companyrightexists
\companyrightblock
\fi
\endgroup
}
\newcommand\companyrolestringvcard{%
\ifcsname Xtitle\endcsname
\Xtitle
\fi
\ifcsname Xrole\endcsname
\ifcsname Xtitle\endcsname ,\ \fi
\Xrole
\fi
\ifcsname Xcompany\endcsname
\ifcsname Xtitle\endcsname
\ \Xcompany
\else
\ifcsname Xrole\endcsname
\ \Xcompany
\else
\Xcompany
\fi
\fi
\fi
}
\newcommand\displayname{%
\ifhaspersonalname{\personalname}{\companybrandingline}%
}
\newcommand\BCQ@headernameformat[1]{%
\ifdefstring{\BCQ@headeremphasis}{company}{\bfseries #1}{%
\ifdefstring{\BCQ@headeremphasis}{balanced}{{\large\bfseries #1}}{%
{\large\bfseries #1}%
}%
}%
}
\newcommand\BCQ@headercompanyformat[1]{%
\ifdefstring{\BCQ@headeremphasis}{company}{{\large #1}}{%
\ifdefstring{\BCQ@headeremphasis}{balanced}{{\large #1}}{#1}%
}%
}
\newcommand\BCQ@appendvcardposition{%
\ifhaspersonalnamevcard{%
\ (\companyrolestringvcard)%
}{%
\companyrolestringvcard
}%
}
\newcommand\BCQ@buildname{%
\ifhaspersonalnamevcard{%
\personalnamevcard
\ifcsname Xtitle\endcsname
\BCQ@appendvcardposition
\else
\ifcsname Xrole\endcsname
\BCQ@appendvcardposition
\else
\ifcsname Xcompany\endcsname
\BCQ@appendvcardposition
\fi
\fi
\fi
}{%
\companyrolestringvcard
}%
}
\let\BCQ@cachedname\@empty
\newcommand\BCQ@setnamecache{%
\begingroup
\edef\BCQ@tmp{\BCQ@buildname}%
\global\let\BCQ@cachedname\BCQ@tmp
\endgroup
}
\newcommand\name{%
\ifx\BCQ@cachedname\@empty
\BCQ@buildname
\else
\BCQ@cachedname
\fi
}
\newcommand\BCQ@vcardversionline{\BCQ@vcardversion}
\newcommand\BCQ@vcardtypeparam{%
\ifcsdef{Xtype}{;TYPE=\Xtype}{}%
}
\newcommand\BCQ@vcardteltype{%
\ifcsdef{Xtype}{\Xtype,voice}{voice}%
}
\newcommand\BCQ@vcardtel{%
TEL;VALUE=uri;TYPE=\BCQ@vcardteltype,text:tel:\Xphone\BCQ@nl
}
\newcommand\BCQ@vcardpobox{\ifcsdef{Xpobox}{\Xpobox}{}}
\newcommand\BCQ@vcardextaddr{\ifcsdef{Xextaddr}{\Xextaddr}{}}
\newcommand\BCQ@vcardstreet{\ifcsdef{Xstreet}{\Xstreet}{}}
\newcommand\BCQ@vcardcity{\ifcsdef{Xcity}{\Xcity}{}}
\newcommand\BCQ@vcardregion{\ifcsdef{Xregion}{\Xregion}{}}
\newcommand\BCQ@vcardzip{\ifcsdef{Xzip}{\Xzip}{}}
\newcommand\BCQ@vcardcountry{\ifcsdef{Xcountry}{\Xcountry}{}}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% vcard - the content of the vcard
% newline selection: default LF (robust for qrcode). Optional CRLF if crlf option set.
{\catcode`\^^M=12\gdef\BCQ@carriagereturn{^^M}}% literal CR (catcode 12)
{\catcode`\^^J=12\gdef\BCQ@linefeed{^^J}}% literal LF (catcode 12)
\ifBCQ@crlf
\def\BCQ@nl{\BCQ@carriagereturn\BCQ@linefeed}% CRLF
\else
\def\BCQ@nl{\BCQ@linefeed}% LF only
\fi
% vcard assembly (version 4.0 retained). CRLF improves iOS import robustness.
\newcommand\vcard{BEGIN:VCARD\BCQ@nl
VERSION:\BCQ@vcardversionline\BCQ@nl
\ifhaspersonalnamevcard{N:\cond{Xfamilynames};\cond{Xgivennames};\cond{Xadditionalnames};\cond{Xhonoricprefix};\cond{Xhonoricsuffix}\BCQ@nl}{}
\ifhaspersonalnamevcard{FN:\personalnamefn\BCQ@nl}{\ifexists{Xcompany}{FN:\Xcompany\BCQ@nl}}
\ifexists{Xcompany}{ORG:\Xcompany\BCQ@nl}
\ifexists{Xtitle}{TITLE:\Xtitle\BCQ@nl}
\ifexists{Xrole}{ROLE:\Xrole\BCQ@nl}
\ifexists{printaddress}{\ifhasaddressvcard{ADR:\BCQ@vcardpobox;\BCQ@vcardextaddr;\BCQ@vcardstreet;\BCQ@vcardcity;\BCQ@vcardregion;\BCQ@vcardzip;\BCQ@vcardcountry\BCQ@nl}{}}
\ifexists{Xphone}{\BCQ@vcardtel}
\ifexists{Xemail}{EMAIL\BCQ@vcardtypeparam:\Xemail\BCQ@nl}
\ifexists{Xjabber}{IMPP;TYPE=XMPP:\Xjabber\BCQ@nl}
\ifexists{Xmatrixorg}{IMPP;TYPE=MATRIX:\Xmatrixorg\BCQ@nl}
\ifexists{Xcloud}{URL:https://nextcloud.com/federation/\#\Xcloud\BCQ@nl}
\ifexists{Xhomepage}{URL:https://\Xhomepage\BCQ@nl}
\ifexists{Xwordpress}{URL:https://\Xwordpress\BCQ@nl}
\ifexists{Xdrupal}{URL:https://\Xdrupal\BCQ@nl}
\ifexists{Xjoomla}{URL:https://\Xjoomla\BCQ@nl}
\ifexists{Xwikipedia}{URL:https://\lang.wikipedia.org/wiki/\Xwikipedia\BCQ@nl}
\ifexists{Xlink}{URL:https://\Xlink\BCQ@nl}
\ifexists{Xworld}{URL:https://\Xworld\BCQ@nl}
\ifexists{Xgit}{URL:https://\Xgit\BCQ@nl}
\ifexists{Xgitea}{URL:https://\Xgitea\BCQ@nl}
\ifexists{Xgithub}{URL:https://github.com/\Xgithub\BCQ@nl}
\ifexists{Xfacebook}{URL:https://facebook.com/\Xfacebook\BCQ@nl}
\ifexists{Xtwitter}{URL:https://twitter.com/\Xtwitter\BCQ@nl}
\ifexists{Xyoutube}{URL:https://youtube.com/user/\Xyoutube\BCQ@nl}
\ifexists{Xgoogle}{URL:https://plus.google.com/+\Xgoogle\BCQ@nl}
\ifexists{Xpgpurl}{KEY;MEDIATYPE=application/pgp-keys:\Xpgpurl\BCQ@nl}
\ifexists{Xpgpfingerprint}{KEY:data:application/x-pgp-fingerprint,\Xpgpfingerprint\BCQ@nl}
END:VCARD\BCQ@nl}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% vcard - the content of the vcard % formatcountry - format country based on length and options
\newcommand\vcard{BEGIN:VCARD^^J \newcommand\formatcountry{%
VERSION:4.0^^J \ifcsdef{Xcountry}{%
N:\cond{Xfamilynames};\cond{Xgivennames};\cond{Xadditionalnames};\cond{Xhonoricprefix};\cond{Xhonoricsuffix}^^J \ifvisible{Xcountry}{%
FN:\name\ifexists{Xadditionalnames}{\ifcsempty{name}{}{\ }\Xadditionalnames}^^J \def\BCQ@shouldinline{false}%
\ifexists{printaddress}{ADR\ifexists{Xtype}{;TYPE=\Xtype}:\cond{Xpobox};\cond{Xextaddr};\cond{Xstreet};\cond{Xcity};\cond{Xregion};\cond{Xzip};\cond{Xcountry}^^J} \def\BCQ@haszipcity{false}%
\ifexists{Xphone}{TEL;VALUE=uri;TYPE=\ifexists{Xtype}{\Xtype,}voice,text:tel:\Xphone^^J} \ifvisible{Xcity}{\def\BCQ@haszipcity{true}}{}%
\ifexists{Xemail}{EMAIL\ifexists{Xtype}{;TYPE=\Xtype}:\Xemail^^J} \ifvisible{Xzip}{\def\BCQ@haszipcity{true}}{}%
\ifexists{Xjabber}{IMPP;TYPE=XMPP:\Xjabber^^J} % Check countryformat option
\ifexists{Xmatrixorg}{IMPP;TYPE=MATRIX:\Xmatrixorg^^J} \ifdefstring{\BCQ@countryformat}{inline}{%
\ifexists{Xcloud}{URL:https://nextcloud.com/federation/\#\Xcloud^^J} \def\BCQ@shouldinline{true}%
\ifexists{Xhomepage}{URL:https://\Xhomepage^^J} }{%
\ifexists{Xwordpress}{URL:https://\Xwordpress^^J} \ifdefstring{\BCQ@countryformat}{below}{%
\ifexists{Xdrupal}{URL:https://\Xdrupal^^J} \def\BCQ@shouldinline{false}%
\ifexists{Xjoomla}{URL:https://\Xjoomla^^J} }{%
\ifexists{Xwikipedia}{URL:https://\lang.wikipedia.org/wiki/\Xwikipedia^^J} % auto mode: check length
\ifexists{Xlink}{URL:https://\Xlink^^J} \StrLen{\Xcountry}[\BCQ@countrylen]%
\ifexists{Xworld}{URL:https://\Xworld^^J} \ifnum\BCQ@countrylen<4\relax%
\ifexists{Xgit}{URL:https://\Xgit^^J} % Short country code AND city/zip exists inline
\ifexists{Xgitea}{URL:https://\Xgitea^^J} \ifdefstring{\BCQ@haszipcity}{true}{%
\ifexists{Xgithub}{URL:https://github.com/\Xgithub^^J} \def\BCQ@shouldinline{true}%
\ifexists{Xfacebook}{URL:https://facebook.com/\Xfacebook^^J} }{}%
\ifexists{Xtwitter}{URL:https://twitter.com/\Xtwitter^^J} \fi%
\ifexists{Xyoutube}{URL:https://youtube.com/user/\Xyoutube^^J} }%
\ifexists{Xgoogle}{URL:https://plus.google.com/+\Xgoogle^^J} }%
\ifexists{Xpgpurl}{KEY;MEDIATYPE=application/pgp-keys:\Xpgpurl^^J} % Output country
\ifexists{Xpgpfingerprint}{KEY:data:application/x-pgp-fingerprint,\Xpgpfingerprint^^J} \ifdefstring{\BCQ@shouldinline}{true}{%
END:VCARD^^J} \Xcountry\ \textemdash\ \conddisplay{Xzip} \conddisplay{Xcity}%
}{%
\conddisplay{Xzip} \conddisplay{Xcity}
\Xcountry
}%
}{%
\conddisplay{Xzip} \conddisplay{Xcity}%
}%
}{
\conddisplay{Xzip} \conddisplay{Xcity}%
}%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% address - the address as shown in the textbox % address - the address as shown in the textbox
\newcommand\address{ \newcommand\address{
\cond{Xpobox} \conddisplay{Xpobox}
\cond{Xextaddr} \conddisplay{Xextaddr}
\cond{Xstreet} \conddisplay{Xstreet}
\cond{Xzip} \cond{Xcity} \formatcountry
\cond{Xregion} \cond{Xcountry} \conddisplay{Xregion}
} }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% inserttext - assemble the textbox % inserttext - assemble the textbox
\newcommand\inserttext{ \newcommand\inserttext[1][\textpercents\textwidth]{
%\frame %\frame
{ {
\begin{minipage}[c][\heightscale][c]{\textpercents\textwidth} \begin{minipage}[c][\heightscale][c]{#1}
\ifBCQ@rightalign\begin{flushright}\fi \ifBCQ@rightalign\begin{flushright}\fi
\ifexists{printaddress}{ \ifexists{printaddress}{
\ifBCQ@iconleft \ifhasaddressvisible{%
\ifBCQ@icon\parbox[c]{1em}{\faMapMarker}\ \ifBCQ@fill\hfill\fi\fi \ifBCQ@iconleft
%\frame{ \ifBCQ@icon\parbox[c]{1em}{\faMapMarker}\ \ifBCQ@fill\hfill\fi\fi
%\pbox[t]{\dimexpr\textwidth-2em\relax}{ \begin{varwidth}{\dimexpr\textwidth-2em\relax}
\begin{varwidth}{\dimexpr\textwidth-2em\relax} \ifBCQ@rightalign\enforceright\fi\address
\ifBCQ@rightalign\enforceright\fi\address \end{varwidth}
\end{varwidth} \else
%} \begin{varwidth}{\dimexpr\textwidth-2em\relax}
%} \ifBCQ@rightalign\enforceright\fi\address
\else \end{varwidth}
%\pbox[t]{\dimexpr\textwidth-2em\relax}{ \ifBCQ@icon\ifBCQ@fill\hfill\fi\ \parbox[c]{1em}{\faMapMarker}\fi
\begin{varwidth}{\dimexpr\textwidth-2em\relax} \fi
\ifBCQ@rightalign\enforceright\fi\address \vspace{1em}
\end{varwidth} }{}%
%} }
\ifBCQ@icon\ifBCQ@fill\hfill\fi\ \parbox[c]{1em}{\faMapMarker}\fi
\fi \insa[tel:]{Xphone}{faMobile}\insa[mailto:]{Xemail}{Email}\insa[xmpp]{Xjabber}{faCommentsO}\insa[matrix.org]{Xmatrixorg}{faCommentsO}\insa[nextcloud-id]{Xcloud}{faCloud}\insa[\protdisplay]{Xhomepage}{faHome}\insa[\protdisplay]{Xwordpress}{faWordpress}\insa[\protdisplay]{Xdrupal}{faDrupal}\insa[\protdisplay]{Xjoomla}{faJoomla}\insa[{\protprefix}\lang.wikipedia.org/wiki/]{Xwikipedia}{faWikipediaW}\insa[\protdisplay]{Xlink}{faLink}\insa[\protdisplay]{Xworld}{faGlobe}\insa[\protdisplay]{Xgit}{faGit}\insa[\protdisplay]{Xgitea}{faGithubAlt}\insa[{\protprefix}github.com/]{Xgithub}{faGithub}\insa[{\protprefix}facebook.com/]{Xfacebook}{faFacebook}\insa[{\protprefix}twitter.com/]{Xtwitter}{faTwitter}\insa[{\protprefix}youtube.com/user/]{Xyoutube}{faYoutube}\insa[{\protprefix}plus.google.com/+]{Xgoogle}{faGooglePlus}
\vspace{1em}
}
\insa[tel:]{Xphone}{faMobile}\insa[mailto:]{Xemail}{Email}\insa[xmpp]{Xjabber}{faCommentsO}\insa[matrix.org]{Xmatrixorg}{faCommentsO}\insa[nextcloud-id]{Xcloud}{faCloud}\insa[\protdisplay]{Xhomepage}{faHome}\insa[\protdisplay]{Xwordpress}{faWordpress}\insa[\protdisplay]{Xdrupal}{faDrupal}\insa[\protdisplay]{Xjoomla}{faJoomla}\insa[{\protprefix}\lang.wikipedia.org/wiki/]{Xwikipedia}{faWikipediaW}\insa[\protdisplay]{Xlink}{faLink}\insa[\protdisplay]{Xworld}{faGlobe}\insa[\protdisplay]{Xgit}{faGit}\insa[\protdisplay]{Xgitea}{faGithubAlt}\insa[{\protprefix}github.com/]{Xgithub}{faGithub}\insa[{\protprefix}facebook.com/]{Xfacebook}{faFacebook}\insa[{\protprefix}twitter.com/]{Xtwitter}{faTwitter}\insa[{\protprefix}youtube.com/user/]{Xyoutube}{faYoutube}\insa[{\protprefix}plus.google.com/+]{Xgoogle}{faGooglePlus}
\ifBCQ@rightalign\end{flushright}\fi \ifBCQ@rightalign\end{flushright}\fi
\end{minipage} \end{minipage}
} }
} }
\newcommand\insertcenteredcontent{%
\vspace*{\fill}
\begin{center}
\ifcsdef{Xcentercontent}{%
\Xcentercontent
}{%
{\bfseries\cond{displayname}}%
\ifvisible{Xcompany}{\\\Xcompany}{}%
\ifvisible{Xtitle}{\\\Xtitle}{}%
\ifvisible{Xrole}{\\\Xrole}{}%
\ifvisible{Xhomepage}{\\\protdisplay\Xhomepage}{}%
\ifvisible{Xemail}{\\\Xemail}{}%
}%
\end{center}
\vspace*{\fill}
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% insertqrcode - insert the qr-code % insertqrcode - insert the qr-code with optional white background
\newcommand\insertqrcode{ \newcommand\insertqrcode{
%\frame % Use local overrides if specified, otherwise use global options
{ \BCQ@resolveusedoption{BCQ@qrbgopacity@local}{\BCQ@qrbgopacity}{\BCQ@qrbgopacity@used}%
\begin{minipage}[c][\heightscale][c]{\imagepercents\textwidth} \BCQ@resolveusedoption{BCQ@qrlogoscale@local}{\BCQ@qrlogoscale}{\BCQ@qrlogoscale@used}%
\qrcode[level=Q,version=0,height=\textwidth]{\vcard} %\frame
\end{minipage} {
\begin{minipage}[c][\heightscale][c]{\imagepercents\textwidth}
\begin{tikzpicture}
% White background behind QR code (for readability over background images)
\node[fill=white, opacity=\BCQ@qrbgopacity@used, inner sep=0pt, outer sep=0pt, minimum size=\textwidth] (bg) at (0,0) {};
% QR code on top
\node[inner sep=0pt, outer sep=0pt] (qr) at (0,0) {%
% QR code with optional qrlogo overlay in center
\ifcsdef{Xqrlogo}{%
\begin{tikzpicture}
\node[inner sep=0pt] (qr2) {{\color{\BCQ@qrcolor}\qrcode[level=\BCQ@qreclevel,version=0,height=\textwidth]{\vcard}}};
% Logo with transparent background preserved (no fill), padding still applied
% qrlogoscale/scale is unitless fraction (0.25 = 25% of QR width)
\node[inner sep=\BCQ@qrlogoborder\textwidth] at (qr2.center) {%
\BCQ@graphiccontent{\Xqrlogo}{width=\BCQ@qrlogoscale@used\textwidth}%
};
\end{tikzpicture}%
}{%
% No qrlogo defined, just show QR code
{\color{\BCQ@qrcolor}\qrcode[level=\BCQ@qreclevel,version=0,height=\textwidth]{\vcard}}%
}%
};
\end{tikzpicture}
\end{minipage}
} }
} }
@@ -242,44 +953,121 @@ END:VCARD^^J}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% insertname - insert the name on the top % insertname - insert the name on the top
\newcommand\insertname{ \newcommand\insertname{
%\frame % typeset name into box for measurement
%\begin{minipage}{\textwidth} \sbox{\BCQ@namebox}{\bfseries\cond{displayname}}%
%\pbox[t]{0.9\textwidth} % Set default logoheight if not specified: 4em with company, 2em without
{\bfseries \ifx\BCQ@logoheight\@empty
\ifcsdef{Xcompany}{\def\BCQ@logoheight{4em}}{\def\BCQ@logoheight{2em}}%
\cond{name} \fi
% Use local height override if specified, otherwise use global logoheight
\cond{Xadditionalnames} \BCQ@resolveusedoption{BCQ@logoheight@local}{\BCQ@logoheight}{\BCQ@logoheight@used}%
% Store logo height as dimension for heightscale calculation
} \ifcsdef{Xlogo}{%
%\end{minipage} \sbox{\BCQ@logobox}{\BCQ@graphiccontent{\Xlogo}{height=\BCQ@logoheight@used}}%
\setlength{\BCQ@logoheightdimen}{\BCQ@logoheight@used}%
\setlength{\BCQ@namecolumnwidth}{\dimexpr\textwidth-\wd\BCQ@logobox-\BCQ@logosep\relax}%
}{%
\setlength{\BCQ@logoheightdimen}{0pt}%
\setlength{\BCQ@namecolumnwidth}{\textwidth}%
}%
% Compute heightscale after logo height is known
\computeheightscale
\ifcsdef{Xlogo}{% logo defined
% Logo next to name: dynamic columns (logo natural width, name uses remaining space)
\setlength{\BCQ@logosepused}{\BCQ@logosep}%
\setlength{\BCQ@namewidth}{\dimexpr\textwidth-\wd\BCQ@logobox-\BCQ@logosepused-\padding-1mm\relax}%
\ifdim\BCQ@namewidth<0pt
\setlength{\BCQ@logosepused}{0pt}%
\setlength{\BCQ@namewidth}{\dimexpr\textwidth-\wd\BCQ@logobox-\padding-1mm\relax}%
\ifdim\BCQ@namewidth<0pt\setlength{\BCQ@namewidth}{0pt}\fi
\fi
\setlength{\BCQ@namecolumnwidth}{\BCQ@namewidth}%
\begin{minipage}{\textwidth}
\begin{minipage}[c]{\wd\BCQ@logobox}% logo column
\usebox{\BCQ@logobox}%
\end{minipage}
\hspace{\BCQ@logosepused}
\begin{minipage}[c]{\BCQ@namewidth}% name column
\ifBCQ@rightalign\raggedleft\fi% apply alignment
\BCQ@headernameformat{\cond{displayname}}%
\BCQ@insertcompanyline
\end{minipage}
\end{minipage}
}{% no logo: just name
\BCQ@headernameformat{\cond{displayname}}%
\BCQ@insertcompanyline
}
} }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% drawcard - assemble all blocks into the visiting card % drawcardcontent - assemble all blocks (name, text, qr, pgp)
\newcommand\drawcard{ \newcommand\drawcardcontent{
\ifBCQ@rightalign\begin{flushright}\fi \BCQ@setnamecache
\insertname \ifdefstring{\BCQ@layout}{centered}{%
\noindent\makebox[\linewidth]{\rule{\paperwidth}{0.4pt}} % horizontal line \insertcenteredcontent
\vfill }{%
\ifBCQ@qrfirst \ifBCQ@rightalign\begin{flushright}\fi
\insertqrcode \ifBCQ@header
\hfill \insertname
\inserttext \noindent\makebox[\linewidth]{\rule{\paperwidth}{0.4pt}} % horizontal line
\else \fi
\inserttext \vfill
\hfill \ifBCQ@qr
\insertqrcode \ifBCQ@qrfirst
\fi \insertqrcode
\ifexists{Xpgpfingerprint}{ \hfill
\vfill \inserttext
\ifBCQ@iconleft \else
\faLock\ifBCQ@hint{\tiny\ pgp}\fi\hfill{\small\Xpgpfingerprint} \inserttext
\else \hfill
{\small\Xpgpfingerprint}\hfill\ifBCQ@hint{\tiny{pgp\ }}\fi\faLock \insertqrcode
\fi \fi
} \else
\ifBCQ@rightalign\end{flushright}\fi \inserttext[\textwidth]
\fi
\ifexists{Xpgpfingerprint}{
\vfill
\ifBCQ@iconleft
\faLock\ifBCQ@hint{\tiny\ pgp}\fi\hfill{\small\Xpgpfingerprint}
\else
{\small\Xpgpfingerprint}\hfill\ifBCQ@hint{\tiny{pgp\ }}\fi\faLock
\fi
}
\ifBCQ@rightalign\end{flushright}\fi
}%
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% drawcard - main card with optional background
\newcommand\drawcard[1][]{
\def\BCQ@drawcardopts{#1}%
\ifx\BCQ@drawcardopts\@empty\else
\setkeys{BCQ@runtime}{#1}%
\fi
% Use local overrides if specified, otherwise use global options
\BCQ@resolveusedoption{BCQ@bgscale@local}{\BCQ@bgscale}{\BCQ@bgscale@used}%
\BCQ@resolveusedoption{BCQ@bgopacity@local}{\BCQ@bgopacity}{\BCQ@bgopacity@used}%
% Handle background
\ifcsdef{Xbackground}{%
\IfFileExists{\Xbackground}{%
% It's an image file: add to background using eso-pic (no layout impact)
\AddToShipoutPictureBG*{%
\AtPageCenter{%
\begin{tikzpicture}[overlay]
\node[inner sep=0pt, opacity=\BCQ@bgopacity@used] at (0,0) {%
\setlength{\BCQ@bgimagedimen}{\dimexpr\BCQ@bgscale@used\paperheight\relax}%
\includegraphics[height=\BCQ@bgimagedimen]{\Xbackground}%
};
\end{tikzpicture}%
}%
}%
}{%
% Not a file: treat as color
\pagecolor{\Xbackground}%
}%
}{}%
% Draw card content
\drawcardcontent
} }
@@ -287,32 +1075,60 @@ END:VCARD^^J}
% cut / crop marks % cut / crop marks
\RequirePackage[\papersize,noinfo,center,pdftex]{crop} \RequirePackage[\papersize,noinfo,center,pdftex]{crop}
\newcommand\tl{ \newcommand\tl{
\begin{picture}(0,0) \begin{picture}(0,0)
\thinlines\unitlength1mm \color{\BCQ@color}
\put(-\border,0){\line(1,0){\cutlen}} \thinlines\unitlength1mm
\put(0,\border){\line(0,-1){\cutlen}} \put(-\border,0){\line(1,0){\cutlen}}
\end{picture} \put(0,\border){\line(0,-1){\cutlen}}
\end{picture}
} }
\newcommand\tr{ \newcommand\tr{
\begin{picture}(0,0) \begin{picture}(0,0)
\thinlines\unitlength1mm \color{\BCQ@color}
\put(\border,0){\line(-1,0){\cutlen}} \thinlines\unitlength1mm
\put(0,\border){\line(0,-1){\cutlen}} \put(\border,0){\line(-1,0){\cutlen}}
\end{picture} \put(0,\border){\line(0,-1){\cutlen}}
\end{picture}
} }
\newcommand\bl{ \newcommand\bl{
\begin{picture}(0,0) \begin{picture}(0,0)
\thinlines\unitlength1mm \color{\BCQ@color}
\put(-\border,0){\line(1,0){\cutlen}} \thinlines\unitlength1mm
\put(0,-\border){\line(0,1){\cutlen}} \put(-\border,0){\line(1,0){\cutlen}}
\end{picture} \put(0,-\border){\line(0,1){\cutlen}}
\end{picture}
} }
\newcommand\br{ \newcommand\br{
\begin{picture}(0,0) \begin{picture}(0,0)
\thinlines\unitlength1mm \color{\BCQ@color}
\put(\border,0){\line(-1,0){\cutlen}} \thinlines\unitlength1mm
\put(0,-\border){\line(0,1){\cutlen}} \put(\border,0){\line(-1,0){\cutlen}}
\end{picture} \put(0,-\border){\line(0,1){\cutlen}}
\end{picture}
} }
\cropdef[]\tl\tr\bl\br{cut} \cropdef[]\tl\tr\bl\br{cut}
\crop[cut] \ifBCQ@cutmarks
\crop[cut]
\else
\crop[off]
\fi
\newcommand\companylogocontent{%
\begingroup
\edef\BCQ@companylogoscan{\expandafter\detokenize\expandafter{\Xcompanylogo}}%
\IfSubStr{\BCQ@companylogoscan}{\string\\}{%
\endgroup
\Xcompanylogo
}{%
\xdef\BCQ@companylogopath{\BCQ@companylogoscan}%
\endgroup
\IfFileExists{\BCQ@companylogopath}{%
\edef\BCQ@companylogoheightused{1.5em}%
\ifcsdef{Xcompanylogoheight}{%
\edef\BCQ@companylogoheightused{\Xcompanylogoheight}%
}{}%
\includegraphics[height=\BCQ@companylogoheightused]{\BCQ@companylogopath}%
}{%
\Xcompanylogo
}%
}%
}
+2 -2
View File
@@ -13,9 +13,9 @@ AC_CHECK_PROG([pandoc])
AC_CHECK_PROG([convert]) AC_CHECK_PROG([convert])
AC_CHECK_PROG([xelatex]) AC_CHECK_PROG([xelatex])
EXAMPLES="example john-doe-hongkong \ EXAMPLES="centered-backside-example example john-doe-hongkong \
peter-muster-example-company-zuerich special-papersize \ peter-muster-example-company-zuerich special-papersize \
texstudio_d30266" texstudio_d30266 photo-example photo-in-qr-example"
AC_SUBST(EXAMPLES) AC_SUBST(EXAMPLES)
+10
View File
@@ -0,0 +1,10 @@
use strict;
use warnings;
use Cwd qw(abs_path);
use File::Basename qw(dirname);
use File::Spec;
my $this_dir = dirname(abs_path(__FILE__));
my $root_rc = File::Spec->catfile($this_dir, '..', '.latexmkrc');
do $root_rc if -e $root_rc;
Binary file not shown.
+18
View File
@@ -0,0 +1,18 @@
% !TeX program = xelatex
\documentclass{businesscard-qrcode}
\type{home}
\givennames{Anna}
\familynames{Beispiel}
\street{Musterweg\ 7}
\city{Zürich}
\zip{8000}
\country{CH}
\phone{+41\ 44\ 123\ 45\ 67}
\email{anna@example.ch}
\homepage{example.ch}
\background{yellow!20}
\begin{document}
\drawcard
\end{document}
Binary file not shown.
+20
View File
@@ -0,0 +1,20 @@
% !TeX program = xelatex
\documentclass[bgscale=1.2,bgopacity=0.6,qrbgopacity=0.5,logoheight=6em,qrlogoscale=0.5]{businesscard-qrcode}
\type{home}
\givennames{Petra}
\familynames{Test}
\company{Example\ Company\ Ltd.}
\street{Bildstrasse\ 99}
\city{Basel}
\zip{4000}
\country{CH}
\phone{+41\ 61\ 123\ 45\ 67}
\email{petra@example.ch}
\background{background.png}
\logo{photo.png}
\qrlogo[scale=.6]{logo.png}
\begin{document}
\drawcard
\end{document}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 MiB

+4
View File
@@ -0,0 +1,4 @@
% Local forwarder for compiling examples from this repository checkout.
% Ensures examples use ../businesscard-qrcode.cls instead of a globally installed class.
\input{../businesscard-qrcode.cls}
\endinput
Binary file not shown.
+29
View File
@@ -0,0 +1,29 @@
\documentclass[textwidth=0.58,qrwidth=0.35,qrfirst]{businesscard-qrcode}
\type{work}
\givennames{John}
\familynames{Doe}
\title{CEO}
\company{My\ Company\ LTD}
\email{john.doe@mycompany.ltd}
\homepage{mycompany.ltd}
\phone{+41\ 44\ 123\ 45\ 67}
\street{Example\ Street\ 1}
\zip{8000}
\city{Z\"urich}
\country{Switzerland}
\begin{document}
% Front side: standard layout with QR
\drawcard
% Back side: centered text-only layout
\newcard
\centercontent{%
{\Large\bfseries My\ Company\ LTD}\par
\vspace{0.8em}
john.doe@mycompany.ltd\par
mycompany.ltd
}
\drawcard[layout=centered,noqr,noheader]
\end{document}
Binary file not shown.

After

Width:  |  Height:  |  Size: 891 KiB

Binary file not shown.
+2 -2
View File
@@ -1,6 +1,6 @@
\documentclass[noaddress,textwidth=0.58,qrwidth=0.35,https,fill,iconright,leftalign,hint,icon,textfirst]{businesscard-qrcode} \documentclass[noaddress,textwidth=0.58,qrwidth=0.35,https,fill,iconright,leftalign,hint,icon,textfirst]{businesscard-qrcode}
\phone{+12 34 567 89 00} \phone{+12\ 34\ 567\ 89\ 00}
\type{home} \type{home}
\honoricprefix{MSc\ ETH} \honoricprefix{MSc\ ETH}
\givennames{Marc} \givennames{Marc}
@@ -26,7 +26,7 @@
\city{Irgendwo} \city{Irgendwo}
\zip{1001} \zip{1001}
\country{Switzerland} \country{Switzerland}
\pgpfingerprint{4C8B 41AF FEC4 ED9D 3AF9 8500 F623 15D0 4D4C 0C62} \pgpfingerprint{4C8B\ 41AF\ FEC4\ ED9D\ 3AF9\ 8500\ F623\ 15D0\ 4D4C\ 0C62}
\pgpurl{https://pgp.mit.edu/pks/lookup?op=get\&search=0xF62315D04D4C0C62} \pgpurl{https://pgp.mit.edu/pks/lookup?op=get\&search=0xF62315D04D4C0C62}
%\jabber{\email} %\jabber{\email}
Binary file not shown.
+12 -1
View File
@@ -4,7 +4,7 @@
\givennames{John} \givennames{John}
\familynames{Doe} \familynames{Doe}
\extaddr{20/F.,\ One\ Kowloon} \extaddr{20/F.,\ One\ Kowloon}
\city{Kowloon Bay} \city{Kowloon\ Bay}
\street{1\ Wang\ Yuen\ Street} \street{1\ Wang\ Yuen\ Street}
\country{Hongkong} \country{Hongkong}
\phone{(852)\ 1234-5678} \phone{(852)\ 1234-5678}
@@ -14,4 +14,15 @@
\begin{document} \begin{document}
%\StrSubstitute{John}{hn}{e} %\StrSubstitute{John}{hn}{e}
\drawcard \drawcard
\newpage
\type{work}
\honoricprefix{Sir}
\givennames{Jonathan}
\familynames{Doe}
\company{My\ Company\ LTD}
\title{CEO}
\email{doe@mycompany.ltd}
\homepage{mycompany.ltd}
\background[scale=1.1,opacity=0.2]{background.png}
\drawcard
\end{document} \end{document}
+146
View File
@@ -0,0 +1,146 @@
<div class="body">
<style>
* {
box-sizing: border-box;
--padding: 2mm;
--paperwidth: 98mm;
--paperheight: 62mm;
--contentwidth: 90mm;
--contentheight: 54mm;
--fontsize: 8pt;
--logoheight: 2cm;
}
div {
border: 1px solid red;
}
.body {
padding: 1cm;
width: 100%;
font-size: var(--fontsize);
display: flex;
justify-content: center;
border: none;
}
.paper {
width: var(--paperwidth);
height: var(--paperheight);
display: flex;
justify-content: center;
align-items: center;
}
.content {
width: var(--contentwidth);
height: var(--contentheight);
display: grid;
grid-template-rows: auto 1fr;
}
header {
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: 1fr 1fr;
grid-template-areas: "logo name" "logo company";
gap: var(--padding);
align-items: center;
align-content: center;
padding-bottom: var(--padding);
border-bottom: 1mm solid black;
margin-bottom: var(--padding);
}
header .logo {
grid-area: logo;
height: var(--logoheight);
width: auto;
}
header .name {
grid-area: name;
text-align: right;
align-self: end;
font-size: larger;
}
header .company {
grid-area: company;
text-align: right;
align-self: start;
font-size: larger;
}
main {
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: 1fr auto;
grid-template-areas: "qrcode text" "pgpkey pgpkey";
column-gap: var(--padding);
row-gap: var(--padding);
}
main .qrcode {
grid-area: qrcode;
aspect-ratio: 1 / 1;
height: 100%;
}
main .text {
grid-area: text;
display: grid;
grid-template-columns: auto 1fr;
grid-template-rows: auto 1fr;
grid-template-areas: "address-prefix address" "info-prefix info";
gap: var(--padding);
align-items: center;
}
main .text .address-prefix {
grid-area: address-prefix;
text-align: left;
}
main .text .address {
grid-area: address;
text-align: right;
}
main .text .info-prefix {
grid-area: info-prefix;
text-align: left;
}
main .text .info {
grid-area: info;
text-align: right;
}
main .pgpkey {
grid-area: pgpkey;
text-align: center;
}
</style>
<div class="paper">
<div class="content">
<header>
<div class="logo">
<img src="marc.png" alt="Marc" />
</div>
<div class="name">Name</div>
<div class="company">Company</div>
</header>
<main>
<div class="qrcode">QR</div>
<div class="text">
<div class="address-prefix">📍</div>
<div class="address">address line 1<br />address line 2</div>
<div class="info-prefix">🖁 tel:<br />✉ mailto:<br />⌂ https://</div>
<div class="info">+41 76 123 45 67<br />email@example.com<br />website.com</div>
</div>
<div class="pgpkey">pgp</div>
</main>
</div>
</div>
</div>
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 653 KiB

+4 -2
View File
@@ -2,7 +2,9 @@ examplesdir = ${docdir}/examples
dist_examples_DATA = $(EXAMPLES:%=%.tex) $(EXAMPLES:%=%.pdf) dist_examples_DATA = $(EXAMPLES:%=%.tex) $(EXAMPLES:%=%.pdf)
%.pdf:%.tex %.pdf:%.tex
xelatex -synctex=1 -interaction=nonstopmode $< TEXINPUTS=..:${srcdir}:$${TEXINPUTS} xelatex -synctex=1 -interaction=nonstopmode $<
CLEANFILES = $(EXAMPLES:%=%.aux) $(EXAMPLES:%=%.log) $(EXAMPLES:%=%.synctex.gz) CLEANFILES = $(EXAMPLES:%=%.aux) $(EXAMPLES:%=%.pdf) $(EXAMPLES:%=%.log) $(EXAMPLES:%=%.synctex.gz) $(EXAMPLES:%=%.fdb_latexmk) $(EXAMPLES:%=%.fls) $(EXAMPLES:%=%.xdv)
MAINTAINERCLEANFILES = makefile.in MAINTAINERCLEANFILES = makefile.in
EXTRA_DIST = .latexmkrc
BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 656 KiB

Binary file not shown.
+26
View File
@@ -0,0 +1,26 @@
\documentclass[qrcolor=pactablue,qrbgopacity=0.4,textwidth=0.6,qrwidth=.35]{businesscard-qrcode}
\usepackage[plain]{pacta}
\background[scale=2,opacity=.6]{background.png}
\logo[height=4em]{marc.png}
\title{CEO}
\role{Founder}
\company[logo={\Pacta[address,height=1.5em]},hide]{Pacta}
%\company{Pacta}
\givennames{Marc}
\familynames{Wäckerlin}
\honoricsuffix{MSc\ ETH}
\type{private}
\phone{+41\ 76\ 434\ 11\ 18}
\email{marc@wäckerlin.ch}
\homepage{marc.wäckerlin.ch}
\street{Florenstrasse\ 66}
\zip{8000}
\city{Zürich}
\country{Schweiz}
\qrlogo[scale=1]{\Pacta[notext,height=3em,bg]}
\begin{document}
\drawcard
\end{document}
%
Binary file not shown.
@@ -9,11 +9,11 @@
\zip{8000} \zip{8000}
\city{Zürich} \city{Zürich}
\country{Switzerland} \country{Switzerland}
\phone{+41 44 123 45 67} \phone{+41\ 44\ 123\ 45\ 67}
\email{peter.muster@example.com} \email{peter.muster@example.com}
\pgpfingerprint{4C8B 41AF FEC4 ED9D 3AF9 8500 F623 15D0 4D4C 0C62} \pgpfingerprint{4C8B\ 41AF\ FEC4\ ED9D\ 3AF9\ 8500\ F623\ 15D0\ 4D4C\ 0C62}
\pgpurl{https://pgp.mit.edu/pks/lookup?op=get\&search=0xF62315D04D4C0C62} \pgpurl{https://pgp.mit.edu/pks/lookup?op=get\&search=0xF62315D04D4C0C62}
\begin{document} \begin{document}
\drawcard \drawcard
\end{document} \end{document}
Binary file not shown.
+27
View File
@@ -0,0 +1,27 @@
% Example 1: Logo next to name (default)
\documentclass[qreclevel=Q]{businesscard-qrcode}
% Demonstrates optional logo placement:
% - Default: logo appears next to name (auto-scaled to name height)
% - Alternative: use logoinqr option to place logo in QR code center (requires qreclevel=H)
\logo{photo.png}
% Try alternative placement by uncommenting these lines and commenting out the \documentclass above:
% \documentclass[logoinqr,qreclevel=H,qrwidth=0.38,textwidth=0.57]{businesscard-qrcode}
\givennames{Alex}
\familynames{Muster}
\company{Example\ Company\ AG}
\type{work}
\phone{+41\ 44\ 123\ 45\ 67}
\email{alex.muster@example.com}
\homepage{example.com}
\github{example}
\gitea{git.example.org/example}
\city{Zürich}
\country{Switzerland}
\begin{document}
\drawcard
\end{document}
Binary file not shown.
+22
View File
@@ -0,0 +1,22 @@
% !TeX program = xelatex
\documentclass[qrbgopacity=0.5]{businesscard-qrcode}
\type{home}
\givennames{Lìsà\ Lündö}
\familynames{Döë}
\company[logo=company-logo.png,height=4em,hide]{Lorem\ Ipsum}
%\company{Lorem\ Ipsum}
\street{Main\ Street\ 123}
\city{New\ York}
\zip{10001}
\country{USA}
\phone{+1\ 234\ 567\ 8900}
\email{ldoe@example.com}
\homepage{example.com}
\logo{photo.png}
\qrlogo[scale=.6]{logo.png}
\background[opacity=0.5,scale=1.2]{background.png}
\begin{document}
\drawcard
\end{document}
Binary file not shown.
+18
View File
@@ -0,0 +1,18 @@
\documentclass[bgscale=1.2,bgopacity=0.6,qrbgopacity=0.8,logoheight=8em]{businesscard-qrcode}
\type{home}
\givennames{Max}
\familynames{Muster}
\company{Big\ Logo\ Example}
\street{Beispielstrasse\ 42}
\city{Winterthur}
\zip{8400}
\country{CH}
\phone{+41\ 52\ 123\ 45\ 67}
\email{max@example.ch}
\logo{photo.png}
\background{background.png}
\begin{document}
\drawcard
\end{document}
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.
+1 -1
View File
@@ -10,7 +10,7 @@
\street{Waldstrasse\ 15} \street{Waldstrasse\ 15}
\zip{9876} \zip{9876}
\city{Nirgendwo} \city{Nirgendwo}
\phone{+41 78 654 32 10} \phone{+41\ 78\ 654\ 32\ 10}
\email{gretchen.huber@example.com} \email{gretchen.huber@example.com}
\begin{document} \begin{document}
Binary file not shown.
+16
View File
@@ -0,0 +1,16 @@
% !TeX program = xelatex
\documentclass{businesscard-qrcode}
\type{home}
\givennames{Max}
\familynames{Muster}
\street{Beispielstrasse\ 42}
\city{Winterthur}
\zip{8400}
\country{CH}
\phone{+41\ 52\ 123\ 45\ 67}
\email{max@example.ch}
\begin{document}
\drawcard
\end{document}
Binary file not shown.
+3 -1
View File
@@ -1,6 +1,6 @@
AUTOMAKE_OPTIONS = foreign AUTOMAKE_OPTIONS = foreign
SUBDIRS = examples screenshots SUBDIRS = examples screenshots
EXAMPLES = background-color-example background-image-example centered-backside-example example john-doe-hongkong peter-muster-example-company-zuerich photo-example photo-in-qr-example photo-large-example special-papersize test-country-short texstudio_d30266
dist_latex_DATA = @PACKAGE_NAME@.cls dist_latex_DATA = @PACKAGE_NAME@.cls
dist_doc_DATA = README.md #@PACKAGE_NAME@.pdf dist_doc_DATA = README.md #@PACKAGE_NAME@.pdf
@@ -10,3 +10,5 @@ dist_doc_DATA = README.md #@PACKAGE_NAME@.pdf
#CLEANFILES = @PACKAGE_NAME@.pdf #CLEANFILES = @PACKAGE_NAME@.pdf
MAINTAINERCLEANFILES = makefile.in aclocal.m4 configure install-sh missing MAINTAINERCLEANFILES = makefile.in aclocal.m4 configure install-sh missing
EXTRA_DIST = .latexmkrc
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 673 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

+68
View File
@@ -0,0 +1,68 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="760" viewBox="0 0 1200 760" role="img" aria-label="businesscard-qrcode standard layout blueprint">
<defs>
<style>
.bg { fill:#f4f6fb; }
.card { fill:#ffffff; stroke:#1f2a44; stroke-width:3; }
.area { fill:#f9fbff; stroke:#44516f; stroke-width:2; }
.sub { fill:#eef3ff; stroke:#5f6f95; stroke-width:1.5; }
.line { stroke:#1f2a44; stroke-width:2.5; }
.h1 { font: 700 30px 'DejaVu Sans', Arial, sans-serif; fill:#18233b; }
.h2 { font: 700 22px 'DejaVu Sans', Arial, sans-serif; fill:#243454; }
.txt { font: 500 17px 'DejaVu Sans', Arial, sans-serif; fill:#243454; }
.small { font: 500 15px 'DejaVu Sans', Arial, sans-serif; fill:#31456f; }
.mono { font: 500 14px 'DejaVu Sans Mono', Consolas, monospace; fill:#31456f; }
.center { text-anchor: middle; dominant-baseline: middle; }
</style>
</defs>
<rect class="bg" x="0" y="0" width="1200" height="760" />
<text class="h1" x="600" y="50" text-anchor="middle">Standard Layout (Normalfall: header + qr + qrfirst)</text>
<rect class="card" x="60" y="80" width="1080" height="620" rx="8" />
<!-- Header -->
<rect class="area" x="90" y="110" width="1020" height="170" rx="4" />
<text class="h2" x="600" y="136" text-anchor="middle">Header Block</text>
<rect class="sub" x="112" y="150" width="230" height="108" rx="4" />
<text class="txt center" x="227" y="190">Optional Name-Logo</text>
<text class="mono center" x="227" y="220">\logo{...}</text>
<rect class="sub" x="360" y="150" width="728" height="48" rx="4" />
<text class="txt center" x="724" y="174">Name Line: honoricprefix + givennames + additionalnames + familynames + honoricsuffix</text>
<rect class="sub" x="360" y="208" width="728" height="50" rx="4" />
<text class="txt center" x="724" y="233">Second line: title/role + [companylogo] + company</text>
<line class="line" x1="90" y1="290" x2="1110" y2="290" />
<text class="small" x="1110" y="284" text-anchor="end">Separator line (only if header=true)</text>
<!-- Body -->
<rect class="area" x="90" y="310" width="1020" height="330" rx="4" />
<text class="h2" x="600" y="336" text-anchor="middle">Main Body Block</text>
<rect class="sub" x="112" y="350" width="420" height="270" rx="4" />
<text class="txt center" x="322" y="385">QR Column (qrwidth)</text>
<rect class="area" x="150" y="410" width="300" height="190" rx="4" />
<text class="txt center" x="300" y="480">QR code</text>
<text class="small center" x="300" y="508">optional \qrlogo</text>
<rect class="sub" x="548" y="350" width="540" height="270" rx="4" />
<text class="txt center" x="818" y="385">Text Column (textwidth)</text>
<rect class="area" x="570" y="410" width="496" height="90" rx="4" />
<text class="txt center" x="818" y="442">Address block (optional)</text>
<text class="small center" x="818" y="468">Map icon + address lines (hidden if no visible address)</text>
<rect class="area" x="570" y="510" width="496" height="92" rx="4" />
<text class="txt center" x="818" y="545">Contact/Social lines</text>
<text class="small center" x="818" y="571">icon | hint | value formatting options</text>
<!-- Footer -->
<rect class="area" x="90" y="648" width="1020" height="34" rx="4" />
<text class="txt center" x="600" y="665">Optional Footer: pgpfingerprint</text>
<!-- Notes -->
<text class="small" x="90" y="726">Swap sides with textfirst. Remove QR with noqr. Remove header with noheader.</text>
</svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

+3 -2
View File
@@ -1,7 +1,8 @@
screenshotdir=${docdir}/screenshots screenshotdir=${docdir}/screenshots
dist_screenshot_DATA=$(EXAMPLES:%=%.jpg) dist_screenshot_DATA=$(EXAMPLES:%=%.png)
%.jpg:${top_srcdir}/examples/%.pdf %.png:${top_srcdir}/examples/%.pdf
convert -density 200 -quality 90 $< $@ convert -density 200 -quality 90 $< $@
CLEANFILES = ${EXAMPLES:%=%.png}
MAINTAINERCLEANFILES = makefile.in MAINTAINERCLEANFILES = makefile.in
Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 766 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB