Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
- **A gallery of eight showcase labels** in the README (GS1-128 pallet, parcel, food, wine, lab specimen, asset tag, shelf tags with data merge, print conditions). Their `.rotula` files and the CSV data are in `docs/showcase`, and the pictures are rendered with Rotula's own PNG export by a test that only runs when `ROTULA_RENDER_SHOWCASE=1` is set.
- **Text fit for wrapped text** (Properties panel, Text fit): choose what a text block does when its text is longer than the box. "Shrink to fit" uses the largest font size, between a smallest and a largest size you set, at which all the text fits; "Grow height" adds lines, up to a limit you set, so all the text shows. With data merge every record gets the size or the lines its own text needs, the canvas shows the same size that prints, and "Do not warn" hides the does-not-fit warning when cutting the text off is what you want. Labels that do not use it are saved exactly as before; a label that does cannot be opened by older versions of Rotula.
- **Print an object only when you want it**: in the new Printing section of the properties, mark an object "Do not print this object" (a note or guide that never reaches the printer or an export), set "Print only when" a field equals, does not equal, contains, is empty or is not empty a value (so a warning can appear on some labels only), and "Lock position" so nothing moves it by accident. The Objects list and the canvas show small No print, Hidden and Locked badges.
- **The Preview window shows a label the way it prints when it is set to print upside down (`^POI`) or mirrored (`^PMY`).** It opens on "As printed", says in one sentence why the picture is turned, and has an "As designed" switch to see it upright. The canvas stays upright for editing and the status bar says "Prints upside down" (or "Prints mirrored"). Imported ZPL with `^POI` / `^PON` and `^PMY` sets the label's setting, so the preview follows it. PNG, JPEG and PDF exports stay as designed.
- **Portuguese (Brazil) and French (Canada)**: the whole interface is now also available in Brazilian Portuguese and Canadian French (View > Language, where each language is listed in its own name), and the installer offers both. On first run Rotula follows Windows: a Portuguese desktop gets Portuguese (Brazil), a French one French (Canada), Spanish stays Spanish and anything else English. Numbers and dates follow the chosen language. A language you picked before stays as it was. The "Language of Rotula" policy (Group Policy / Intune) also accepts `pt-BR` and `fr-CA`.

### Fixed
Expand Down
10 changes: 7 additions & 3 deletions README.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,10 @@ QR, cuadros, líneas, círculos e imágenes monocromáticas (con umbral o tramad

### Vista previa e impresión

La vista previa muestra la etiqueta más grande, tal como se dibujará, y dice con claridad que es aproximada. El cuadro de
La vista previa muestra la etiqueta más grande, tal como se dibujará, y dice con claridad que es aproximada. Una etiqueta
configurada para imprimirse al revés (`^POI`) o en espejo (`^PMY`) se muestra "Como se imprime", con una frase que explica
por qué; cambia a "Como se diseñó" para verla derecha. El lienzo siempre queda derecho para editar, y la barra de estado
indica "Se imprime al revés". El cuadro de
impresión lee la resolución y el tamaño de papel desde el controlador de la impresora, puede enviar una etiqueta de prueba
e imprime en una impresora de Windows o en una impresora de red.

Expand Down Expand Up @@ -577,8 +580,9 @@ Léelas antes de depender de Rotula para etiquetas de producción, e **imprime s
impresa. La aplicación lo avisa.
- **Fuentes de mapa de bits y `FontWidth`.** Las fuentes de mapa de bits integradas de la impresora no se reproducen; el
escalado de ancho solo se aproxima en la vista previa.
- **`^PO` (orientación de impresión) no se previsualiza.** Se escribe en el ZPL, pero la vista previa siempre muestra la
orientación normal.
- **La orientación de impresión (`^PO`) y el espejo (`^PM`) solo se muestran en la ventana Vista previa.** El lienzo y las
exportaciones PNG, JPEG y PDF muestran la etiqueta como se diseñó (derecha); las exportaciones son el diseño, no una imagen
de lo que sale de la impresora.
- **Las variables no sobreviven a un viaje de ida y vuelta por ZPL.** ZPL no puede expresar `{{nombre}}`, así que el ZPL
importado es texto simple hasta que lo edites.
- **El ZPL sin procesar no se escala al convertir el DPI.** Los comandos desconocidos conservados como ZPL sin procesar
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,9 @@ dithering).

### Preview and print

A live preview shows the label larger, as it will be drawn, and says plainly that it is approximate. The print dialog
A live preview shows the label larger, as it will be drawn, and says plainly that it is approximate. A label set to print
upside down (`^POI`) or as a mirror image (`^PMY`) is shown "As printed" with a sentence saying why; switch to "As designed"
to see it upright. The canvas always stays upright for editing, and the status bar says "Prints upside down". The print dialog
reads the resolution and paper size from the printer driver, can send a test label, and prints to a Windows printer or a
network printer.

Expand Down Expand Up @@ -565,7 +567,8 @@ Read these before relying on Rotula for production labels, and **always print a
shapes and line breaks can differ slightly from the printed label. The app says so.
- **Bitmap fonts and `FontWidth`.** The printer's built-in bitmap fonts are not reproduced; width scaling is only approximated
in the preview.
- **`^PO` (print orientation) is not previewed.** It is written to the ZPL, but the preview always shows the normal orientation.
- **Print orientation (`^PO`) and mirror (`^PM`) are shown only in the Preview window.** The canvas and the PNG, JPEG and PDF
exports show the label as designed (upright); the exports are artwork, not a picture of the printer's output.
- **Variables do not survive a ZPL round trip.** ZPL cannot express `{{name}}`, so imported ZPL is plain text until you edit it.
- **Raw ZPL is not scaled on DPI conversion.** Unknown commands kept as raw ZPL stay in their original dots when a label is
converted to another resolution, and Rotula warns you.
Expand Down
10 changes: 10 additions & 0 deletions docs/decisions.md
Original file line number Diff line number Diff line change
Expand Up @@ -618,3 +618,13 @@ leaving by accident; it is not a security boundary, because anyone who can edit
Keyboard-wedge scanners end a code with Enter or Tab, which `ScanSequencer` turns into "stay", "next field", "focus Print" or "print". Timing
heuristics (telling a scan from typing by speed) were left out: they misfire on slow PCs and remote sessions, and the terminator already works for
both people and scanners.
## Print orientation preview (Rotula.Rendering)

### ^PO and ^PM are shown "as printed" only in the Preview window
`RenderLabel.Inverted` (^POI) and `RenderLabel.Mirrored` (^PMY) flip the whole drawing about the label's centre inside `LabelRenderer.Draw`, so
bitmaps and PDF pages get the same transform. `LabelDocumentAdapter.ToRenderLabel` never sets them; only `LabelDocumentAdapter.AsPrinted` does,
and only the Preview window asks for it (it opens on "As printed" with an "As designed" switch and a sentence saying why the picture is turned).
The design canvas stays upright because editing an upside-down label (handles, rulers, snapping, typing) would be confusing; the status bar says
"Prints upside down" / "Prints mirrored" instead. PNG, JPEG and PDF exports and the MCP preview stay as designed: they are artwork for documents,
proofs and screens, not a picture of the media leaving the printer, and there is no "as printed" export option to honour. The two flips commute
(inverted and mirrored together is a top-to-bottom flip), so their order is not a question.
4 changes: 2 additions & 2 deletions docs/zpl-coverage.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@ Nothing is silently dropped.
| `^LS` | Label shift | Supported | Yes | Yes | Exact | Shifts every field to the left by a number of dots; a negative value shifts to the right. Written only when it is not zero. |
| `^LT` | Label top | Supported | Yes | Yes | Exact | Moves the whole format down (or up for a negative value) by a few dot rows to fine-tune where it lands on the label. Rotula accepts -240 to 240; most printers only accept -120 to 120. |
| `^MU` | Units of measure | Supported | No | Yes | n/a | Switches the units used by later numbers to dots, inches or millimetres. Values are converted to dots on import and a notice is shown. |
| `^PM` | Mirror the label | Supported | Yes | Yes | No | Prints the whole label as a mirror image, left to right. The on-screen preview does not mirror. |
| `^PO` | Print orientation | Supported | Yes | Yes | No | Prints the whole label rotated by 180 degrees. The on-screen preview always shows the normal orientation. |
| `^PM` | Mirror the label | Supported | Yes | Yes | Exact | Prints the whole label as a mirror image, left to right. The Preview window shows it mirrored ("As printed"); the canvas and the image and PDF exports stay as designed. |
| `^PO` | Print orientation | Supported | Yes | Yes | Exact | Prints the whole label rotated by 180 degrees. The Preview window shows it upside down ("As printed", with a switch to "As designed"); the canvas and the image and PDF exports stay upright. |
| `^PQ` | Print quantity | Supported | Yes | Yes | n/a | Sets how many labels print, how many between pauses, and how many copies of each serial number. |
| `^PW` | Print width | Supported | Yes | Yes | Exact | Sets the width of the printable area in dots. |
| `^XA` | Start of label | Supported | Yes | Yes | n/a | Opens a label format. Everything up to the matching end-of-label command belongs to one label. |
Expand Down
11 changes: 10 additions & 1 deletion src/Rotula.App/Editing/PreviewCache.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ public sealed class PreviewCache : IDisposable
/// <summary>Creates a cache for a session.</summary>
public PreviewCache(EditorSession session) => _session = session;

/// <summary>The label this cache draws (the session's current document).</summary>
public Core.Model.LabelDocument Document => _session.Document;

/// <summary>
/// Values of the data-merge record shown on the canvas, or null to draw the sample values. Changing it must be followed
/// by <see cref="EditorSession.Touch"/> so the cached render is rebuilt.
Expand Down Expand Up @@ -70,10 +73,16 @@ public RenderLabel GetDesignLabel()
/// Draws the label exactly as it prints (objects that are not printed for the shown record are left out). The caller owns and must dispose the
/// result. Returns null and sets <paramref name="errorKey"/> when the label cannot be drawn.
/// </summary>
public RenderResult? RenderPrinted(double scale, out string? errorKey)
/// <param name="scale">Output pixels per printer dot.</param>
/// <param name="errorKey">Message key of the reason the label could not be drawn, or null.</param>
/// <param name="asPrinted">
/// True to turn (^POI) or mirror (^PMY) the picture the way the printer puts it on the media; false shows it as designed.
/// </param>
public RenderResult? RenderPrinted(double scale, out string? errorKey, bool asPrinted = false)
{
errorKey = null;
var label = GetLabel();
if (asPrinted) label = LabelDocumentAdapter.AsPrinted(label, _session.Document);
if (label.WidthDots <= 0 || label.HeightDots <= 0) { errorKey = "Preview.InvalidSize"; return null; }
try { return LabelRenderer.RenderBitmap(label, new RenderOptions { Scale = scale }); }
catch (ArgumentOutOfRangeException) { errorKey = "Preview.TooLarge"; return null; }
Expand Down
13 changes: 13 additions & 0 deletions src/Rotula.App/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,19 @@
<Border Style="{StaticResource StatusSeparator}" />
<TextBlock Text="{Binding CursorText}" MinWidth="120" />
</StackPanel>
<!-- Only for a label the printer turns (^POI) or mirrors (^PMY): the canvas stays upright for editing, so the print difference is named here. -->
<StackPanel Orientation="Horizontal" ToolTip="{loc:T Status.PrintOrientation.Tip}">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding PrintOrientationText}" Value=""><Setter Property="Visibility" Value="Collapsed" /></DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Border Style="{StaticResource StatusSeparator}" />
<TextBlock Text="{Binding PrintOrientationText}" Foreground="{StaticResource AccentBrush}" FontWeight="SemiBold"
AutomationProperties.Name="{loc:T Status.PrintOrientation.Name}" />
</StackPanel>
<Border Style="{StaticResource StatusSeparator}" />
<TextBlock Text="{Binding StatusLabelText}" AutomationProperties.Name="{loc:T Status.LabelInfo}" />
</StackPanel>
Expand Down
42 changes: 42 additions & 0 deletions src/Rotula.App/Resources/Strings.en.resx
Original file line number Diff line number Diff line change
Expand Up @@ -6258,4 +6258,46 @@ Brand and product names belong to their owners; Rotula is not affiliated with th
<data name="Update.OpenFailed" xml:space="preserve">
<value>The browser could not be opened. The release page is {0}</value>
</data>
<data name="Preview.Mode.Name" xml:space="preserve">
<value>Show the label as printed or as designed</value>
</data>
<data name="Preview.AsPrinted" xml:space="preserve">
<value>As printed</value>
</data>
<data name="Preview.AsPrinted.Tip" xml:space="preserve">
<value>Show the label the way it comes out of the printer, turned or mirrored by the label's print settings.</value>
</data>
<data name="Preview.AsDesigned" xml:space="preserve">
<value>As designed</value>
</data>
<data name="Preview.AsDesigned.Tip" xml:space="preserve">
<value>Show the label upright, the way you edit it on the canvas.</value>
</data>
<data name="Preview.Note.PrintedInverted" xml:space="preserve">
<value>Shown as printed: this label's print orientation is set to inverted, so the printer prints it upside down.</value>
</data>
<data name="Preview.Note.PrintedMirrored" xml:space="preserve">
<value>Shown as printed: this label is set to print as a mirror image, so left and right are swapped.</value>
</data>
<data name="Preview.Note.PrintedBoth" xml:space="preserve">
<value>Shown as printed: this label is set to print upside down and as a mirror image.</value>
</data>
<data name="Preview.Note.Designed" xml:space="preserve">
<value>Shown as designed, the way you edit it. Choose "As printed" to see how it comes out of the printer.</value>
</data>
<data name="Status.PrintsInverted" xml:space="preserve">
<value>Prints upside down</value>
</data>
<data name="Status.PrintsMirrored" xml:space="preserve">
<value>Prints mirrored</value>
</data>
<data name="Status.PrintsInvertedMirrored" xml:space="preserve">
<value>Prints upside down, mirrored</value>
</data>
<data name="Status.PrintOrientation.Name" xml:space="preserve">
<value>Print orientation</value>
</data>
<data name="Status.PrintOrientation.Tip" xml:space="preserve">
<value>The canvas shows the label upright so you can edit it. Open the preview to see it as printed. Change this in the label properties.</value>
</data>
</root>
42 changes: 42 additions & 0 deletions src/Rotula.App/Resources/Strings.es.resx
Original file line number Diff line number Diff line change
Expand Up @@ -6258,4 +6258,46 @@ Las marcas y los nombres de producto pertenecen a sus dueños; Rotula no está a
<data name="Update.OpenFailed" xml:space="preserve">
<value>No se pudo abrir el navegador. La página de la versión es {0}</value>
</data>
<data name="Preview.Mode.Name" xml:space="preserve">
<value>Mostrar la etiqueta como se imprime o como se diseñó</value>
</data>
<data name="Preview.AsPrinted" xml:space="preserve">
<value>Como se imprime</value>
</data>
<data name="Preview.AsPrinted.Tip" xml:space="preserve">
<value>Muestra la etiqueta tal como sale de la impresora, girada o reflejada según la configuración de impresión de la etiqueta.</value>
</data>
<data name="Preview.AsDesigned" xml:space="preserve">
<value>Como se diseñó</value>
</data>
<data name="Preview.AsDesigned.Tip" xml:space="preserve">
<value>Muestra la etiqueta derecha, tal como la edita en el lienzo.</value>
</data>
<data name="Preview.Note.PrintedInverted" xml:space="preserve">
<value>Vista como se imprime: la orientación de impresión de esta etiqueta es invertida, así que la impresora la imprime al revés.</value>
</data>
<data name="Preview.Note.PrintedMirrored" xml:space="preserve">
<value>Vista como se imprime: esta etiqueta está configurada para imprimirse en espejo, así que la izquierda y la derecha se intercambian.</value>
</data>
<data name="Preview.Note.PrintedBoth" xml:space="preserve">
<value>Vista como se imprime: esta etiqueta está configurada para imprimirse al revés y en espejo.</value>
</data>
<data name="Preview.Note.Designed" xml:space="preserve">
<value>Vista como se diseñó, tal como la edita. Elija "Como se imprime" para ver cómo sale de la impresora.</value>
</data>
<data name="Status.PrintsInverted" xml:space="preserve">
<value>Se imprime al revés</value>
</data>
<data name="Status.PrintsMirrored" xml:space="preserve">
<value>Se imprime en espejo</value>
</data>
<data name="Status.PrintsInvertedMirrored" xml:space="preserve">
<value>Se imprime al revés y en espejo</value>
</data>
<data name="Status.PrintOrientation.Name" xml:space="preserve">
<value>Orientación de impresión</value>
</data>
<data name="Status.PrintOrientation.Tip" xml:space="preserve">
<value>El lienzo muestra la etiqueta derecha para que pueda editarla. Abra la vista previa para verla como se imprime. Puede cambiarlo en las propiedades de la etiqueta.</value>
</data>
</root>
Loading
Loading