Help us shape the future of Go! Take the 2026 Go Developer Survey

tm2

package module
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 18, 2026 License: MIT Imports: 20 Imported by: 0

README

A Go gopher holding a strip of label tape

tepra.tm2

Make label files for KING JIM's TEPRA LINK 2 app.

Test Coverage Go Reference

TEPRA LINK 2 saves labels as .tm2 files. tepra.tm2 writes them. Type a list once, and get one label per line. Then print from the app, as usual.

It works from an AI assistant over MCP, from the command line, and from Go.

[!IMPORTANT] .tm2 is the format of TEPRA LINK 2 only. TEPRA Creator (テプラ クリエイター), the app for Windows, does not open these files. tepra.tm2 does not write files for TEPRA Creator.

[!WARNING] This is an unofficial tool. KING JIM does not document the .tm2 format.

  • tepra.tm2 writes every key that files from the app have.
  • Each setting was checked on the screen of TEPRA LINK 2 for Android, with an SR-MK1.
  • A new release of the app may change the format.

Installation

Tool
Way How
mise (recommended) mise use -g github:mpyw/tepra.tm2
A release binary Download the archive for your OS and CPU from Releases. Put tm2 on your PATH. checksums.txt has their SHA-256.
From source go install github.com/mpyw/tepra.tm2/cmd/tm2@latest

Releases cover macOS, Linux and Windows, each on amd64 and arm64.

MCP Server

The MCP server is tm2 mcp. First install tm2 as a tool, as above. Then add it to your assistant. For Claude Code:

claude mcp add tm2 -- tm2 mcp
Library
go get github.com/mpyw/tepra.tm2

The package is named tm2.

Usage: As an MCP Server

Ask for labels in your own words. The assistant writes a .tm2 file with the MCP tools. It can also read a .tm2 file and change it, one the app saved too. Then print the file from TEPRA LINK 2.

Usage: As a Tool

One label of two lines:

tm2 text -o sample.tm2 $'サンプル\nテキスト'
wrote sample.tm2: 1 label, 18.2 mm long, on 12 mm tape

[!TIP] $'...' turns \n into a line break in bash and zsh. A line break inside quotes works too. In PowerShell, write "サンプル`nテキスト".

A label per row of a CSV file, each in the size that fits it:

tm2 pages -o pages.tm2 items.csv
wrote pages.tm2: 3 pages, 12.0 to 22.5 mm long, on 12 mm tape

Then print the file from TEPRA LINK 2.

Usage: As a Library

f, err := tm2.NewPages(
	tm2.Tape12mm,
	[]string{"1行目\n2行目", "1行目"},
	tm2.WithAlign(tm2.AlignCenter),
)
if err != nil {
	return err
}
return f.WriteFile("items.tm2")

References

Kinds of label
text pages pour (流し込み)
Labels in a file One One per page One per value
Font size and length Fitted to the label Fitted to each label Same for every label, fitted to the longest
Edit in the app As one label Page by page As pour data, in a table
QR codes and barcodes No No Yes
MCP tool create_text_label create_label_pages create_pour_labels
Command tm2 text tm2 pages tm2 pour
Go NewText NewPages NewPour

[!TIP] For a list of things to label, use pages. Each label gets the size that fits it. Give a length, and every label is as long. Use pour only for QR codes and barcodes, or to edit the labels as one table in the app. Pour lays text out less well: see Layout.

Tapes
Width Go
4, 6, 9, 12, 18, 24, 36 and 50 mm Tape4mm to Tape50mm, or LookupTape(width)

The sizes of each tape come from a file the app wrote on it.

Layout

Size and length:

  • Text fills the height of the tape, unless a font size is given.
  • A label is as long as what is on it, and at least 12 mm with its margins. The app makes no shorter label.
  • A label of a fixed length has its content centred. Text too long for it gets smaller, unless a font size is given.
  • All the labels of a pour file have one font size, the one that fits the value of most lines.

What you see when you edit the label in the app:

  • A border is an empty box of its own, around the text. A border set on a pour drawer itself (BIType) does not show.
  • Inverted text of more than one line is a box per line. In a pour file, each line is a column of its own: Label, Label 2 and on.

What pour cannot do:

  • The text sits at the left of its frame. The app ignores the alignment of a pour drawer.
  • Inverted text is black only behind the letters, not over the whole frame.
  • The text keeps its font size, and its width is an estimate. Bold text and wide letters, such as w and m, can run past the frame.

Pages with a length have none of these limits.

[!NOTE] On 4 mm tape, a border's padding of 1.5 mm leaves no room for text. Give a padding of 0.3 mm there.

Print the file
  1. Send the .tm2 file to your phone, such as through Google Drive.
  2. Open it with TEPRA LINK 2, through the share menu of the OS.
  3. Check the labels in the app, and print.
MCP tools

tm2 mcp serves these on stdin and stdout:

Tool Kind What it does
create_text_label text Writes a file of one label
create_label_pages pages Writes a file of one page per string
create_pour_labels pour Writes a pour file: one label per string
inspect_label Describes a .tm2 file. With full, it also returns every key as JSON, and each picture
edit_label Changes a .tm2 file by a patch

Inputs:

  • The tools that write a file take the tool options, in snake case.
  • A length in mm ends in _mm, and a picture in _path. Examples: font_size, rotate, padding_mm, icon_path.
  • code and column are for create_pour_labels only.
  • Paths must be absolute, for the file and for pictures.
  • A file is not replaced unless overwrite is true. edit_label changes the file at path in place without it. It writes to output instead when given. The label then takes the name of output in the app, unless the patch sets /fileName.
  • A line break in a label is \n.
Commands
Command What it does
tm2 text [options] text Writes one label. A line break in the text breaks it into lines
tm2 pages [options] [file.csv] Writes a page per row of the file
tm2 pour [options] [file.csv] Writes a pour label per row of the file
tm2 inspect [--json] file.tm2 Shows what a .tm2 file holds
tm2 edit [-o out.tm2] [-f] file.tm2 [patch.json] Changes a .tm2 file by a patch
tm2 mcp Serves the MCP tools on stdin and stdout

A pour file of the same items.csv:

tm2 pour -o items.tm2 items.csv
wrote items.tm2: 3 labels, 12.0 mm each, on 12 mm tape

A QR code per URL, one label each:

tm2 pour --code qr -o qr.tm2 urls.csv
wrote qr.tm2: 2 labels, 12.2 mm each, on 12 mm tape

A label of a fixed length, with a rounded border:

tm2 text --length 60 --border rounded --align center -o fixed.tm2 サンプル
wrote fixed.tm2: 1 label, 60.0 mm long, on 12 mm tape

Text turned 90 degrees, and text in white on black:

tm2 text --rotate 90 -o turned.tm2 $'サンプル\nテキスト'
tm2 text --fill inverted --bold -o inverted.tm2 サンプル
wrote turned.tm2: 1 label, 12.0 mm long, on 12 mm tape
wrote inverted.tm2: 1 label, 34.5 mm long, on 12 mm tape
The CSV file

pages and pour read a CSV file of one column. Without a file, or with -, they read stdin.

  • Each row is a label.
  • A line break in a value breaks the label into lines.
  • A value in double quotes may hold line breaks and commas.
  • A double quote in a value is doubled, inside double quotes: "He said ""hi""".
  • Blank rows are skipped. So are spaces around a value.
  • A row of two or more columns is an error.
  • The file must be UTF-8. In Excel, save it as "CSV UTF-8".
  • Rows may end in CRLF, LF or CR.

This items.csv makes three labels:

"1行目
2行目
3行目"
"1行目
2行目"
1行目

[!TIP] A file with one value per line is a CSV file of one column already. Quote only the values that hold a line break, a comma or a double quote. Spreadsheets quote such values when they save a CSV file.

Tool options

text, pages and pour all take these. In pages and pour they apply to every label.

Option Default Meaning
-o, --output (required) The .tm2 file to write. Its name, without .tm2, names the label in the app
-f, --force off Replace the file when it exists
--tape 12 Tape width in mm: 4, 6, 9, 12, 18, 24, 36 or 50
--font-size fit Font size in points. By default the text fills the tape
--bold off Bold text
--align left Where each line goes across: left, center or right
--valign middle Where the text goes down: top, middle or bottom
--rotate 0 Turn the text clockwise: 0, 90, 180 or 270 degrees
--vertical off Write the text top to bottom
--fill none The box behind the text: none, inverted (white on black) or shaded (a light dotted box)
--border none The line around the label: none, box, rounded, top-bottom, top or bottom
--border-width 0.7 The width of the border. 0.35 is thin, 2.8 is thick
--icon none A PNG, JPEG or GIF file to put before the text, as high as the tape prints
--background none A PNG, JPEG or GIF file to stretch under the whole label, such as a frame
--image-mode threshold How pictures turn black and white: threshold, diffusion or screen
--image-threshold 128 The grey level, 0 to 255, below which a pixel is black
--padding 0 Blank between the label's edges and its text, in mm. 1.5 with a border
--margin 1 Blank tape before and after the label, in mm, 1 to 500
--length fit Make the label this long, margins included, in mm, 10 to 3000

Only pour takes these:

Option Default Meaning
--code text Show each value as a code: text, qr, code39, code128 or jan13
--column Label Title of the pour column in the app

[!NOTE] --code jan13 takes 12 digits. The app adds the check digit.

tm2 inspect

tm2 inspect shows what a .tm2 file holds. It reads files the app wrote, too.

$ tm2 inspect items.tm2
file:    items.tm2 (version 2.0.0, saved 2026/10/18 10:15)
tape:    12 mm, pour, label 12.0 mm long, margin 1.0 mm
drawers: /documents/0/drawers
   0 pour   x   1.6  y   1.1  w   6.7  h  10.2 mm  column 0, size 7.5, OTBGoStdR-Normal, keeps its size
rows:    3, column "Label"
    1  1行目 / 2行目 / 3行目
    2  1行目 / 2行目
    3  1行目

A file of pages shows each page. Pages count from 1, as in the app:

$ tm2 inspect pages.tm2
file:    pages.tm2 (version 2.0.0, saved 2026/10/18 10:15)
page 1:
tape:    12 mm, plain, label 12.0 mm long, margin 1.0 mm
drawers: /documents/0/drawers
   0 text   x   1.6  y   1.1  w   6.7  h  10.2 mm  size 7.5, OTBGoStdR-Normal, "1行目\n2行目\n3行目"
page 2:
tape:    12 mm, plain, label 12.2 mm long, margin 1.0 mm
drawers: /documents/1/drawers
   0 text   x   0.0  y   1.1  w  10.2  h  10.2 mm  size 11.5, OTBGoStdR-Normal, "1行目\n2行目"
page 3:
tape:    12 mm, plain, label 22.5 mm long, margin 1.0 mm
drawers: /documents/2/drawers
   0 text   x   0.0  y   1.1  w  20.5  h  10.2 mm  size 23, OTBGoStdR-Normal, "1行目"
  • Each drawer starts with its index. drawers: gives the path of the list, for a patch.
  • After the size and the font come the settings that differ from a new drawer, such as align center or border box 0.7.
  • --json prints every key of the file, at the paths a patch takes. A picture shows as its size.
tm2 edit

tm2 edit changes a .tm2 file by a patch. It reads the patch from a file, or from stdin without one. Without -o, it changes the file in place. With -o, the label takes the name of the new file in the app, as a label made there would. A patch that sets /fileName keeps its own name.

[!WARNING] An edit in place writes over the file, as --force does. A failed write, such as on a full disk, can leave it broken. Keep a copy of a file the app saved, or write to another with -o.

This patch.json changes the third row, and centres the text:

[
  {"op": "replace", "path": "/tableData/2/0", "value": "4行目"},
  {"op": "replace", "path": "/documents/0/drawers/0/TIAlignment", "value": 1}
]
tm2 edit items.tm2 patch.json
wrote items.tm2: 3 labels, 12.0 mm each, on 12 mm tape
Patches

A patch is a JSON Patch (RFC 6902). It applies to the file as tm2 inspect --json prints it. tm2 edit, edit_label and File.Patch take it.

Op What it does
replace Sets the value of a key, or of an item of an array
add Puts an item in an array. - as the index puts it last. On a key, it is replace
remove Takes an item out of an array
move, copy Moves or copies a value from from to path
test Fails the patch unless the value at path is value

What a patch keeps:

Rule Why
A key is not added or removed The app writes every key. A new key would be one no file of the app has
A whole file, document or drawer put in place needs every key it has, and no other A key left out would be written as 0, not as the app sets it. So type changes only with the keys of the new type
A drawer added starts as the app makes one of its type: text, pour or image It needs only type and the keys to change. Its frame is the label's frame
A drawer of a type tm2 does not know may move, but not be copied or changed It is written as it was read, so its identifier cannot change
The empty key after a drawer's identifier stays The app writes it
A copy of a document or drawer, or one with no identifier, gets a new identifier The app gives each one its own
hasPlaceholder is cleared once TIText has text The app shows the placeholder instead of the text while it is set
With two or more pages, each gets MultiplePage The app lists the pages only then
A row of tableData gets empty cells up to 50 The app writes 50 columns
A picture is checked, and a JPEG or GIF is made PNG The app stores pictures as PNG
A value the app crashes on fails the patch Such a file is never written

Either every operation applies, or nothing changes.

[!IMPORTANT] A patch does not lay the label out again. Text made longer keeps its frame, and the app fits it there. Set frame too when the size must change. A frame is x, y, width and height in points. 1 mm is 2.835 points.

image_path in an operation gives a picture, from a PNG, JPEG or GIF file. It is the value of a path that ends in /image, given with no value. Or it is the image of a drawer of type image, given as the value:

[{"op": "add", "path": "/documents/0/drawers/-", "value": {"type": "image", "frame": [0, 0, 20, 20]}, "image_path": "/path/to/logo.png"}]

The numbers of the keys that show in the app:

Key Values
TIAlignment 0 left, 1 center, 2 right
TIVerticalAlignment 0 top, 1 middle, 2 bottom
TIFillMode 0 none, 1 inverted, 2 shaded
Rotate 0 none, 1 180°, 2 270°, 3 90°
BIType 0 none, 1 box, 2 rounded, 3 top-bottom, 4 top, 5 bottom
Attribute (pour) 0 text, 1 QR, 2 CODE39, 3 CODE128, 4 JAN-13
imageMode 1 diffusion, 2 threshold, 3 screen
TIFontName OTBGoStdR-Normal regular, OTBGoStdB-Normal bold
Functions
Function Returns
NewText(tape, text, opts...) A file of one label
NewPages(tape, texts, opts...) A file of a page per string, each fitted
NewPour(tape, column, values, opts...) A pour file of a label per string, under the column's title
ReadFile(path), ParseFile(r) A file read back

A File writes itself with WriteFile or WriteTo. Patch changes it by a patch.

f, err := tm2.ReadFile("items.tm2")
if err != nil {
	return err
}
err = f.Patch(tm2.PatchOp{
	Op:    "replace",
	Path:  "/tableData/2/0",
	Value: jsontext.Value(`"4行目"`),
})
if err != nil {
	return err
}
return f.WriteFile("items.tm2")
Library options

Each With function sets one thing. What no option sets is as the app sets it.

Option Default Meaning
WithName(name) "label" Names the label in the app, without .tm2
WithTime(t) now The file's date
WithFontSize(pt) fit Font size in points. By default the text fills the tape
WithBold() off Bold text
WithAlign(a) AlignLeft Where each line goes across: AlignLeft, AlignCenter or AlignRight
WithVerticalAlign(a) VerticalAlignMiddle Where the text goes down: VerticalAlignTop, VerticalAlignMiddle or VerticalAlignBottom
WithRotation(r) RotationNone Turn the text clockwise: RotationNone, Rotation90, Rotation180 or Rotation270
WithVertical() off Write the text top to bottom
WithFill(m) FillNone The box behind the text: FillNone, FillInverted or FillShaded
WithBorder(b) BorderNone The line around the label: BorderNone, BorderBox, BorderRounded, BorderTopBottom, BorderTop or BorderBottom
WithBorderWidth(w) 0.7 The width of the border
WithIcon(picture) none PNG, JPEG or GIF bytes to put before the text
WithBackground(picture) none PNG, JPEG or GIF bytes to stretch under the whole label
WithImageMode(m) ImageModeThreshold How pictures turn black and white: ImageModeThreshold, ImageModeDiffusion or ImageModeScreen
WithImageThreshold(level) 128 The grey level, 0 to 255, below which a pixel is black
WithPaddingMM(mm) 0 Blank between the label's edges and its text. 1.5 with a border
WithMarginMM(mm) 1 Blank tape before and after the label, 1 to 500
WithLengthMM(mm) fit Make the label this long, margins included, 10 to 3000
WithCode(k) CodeText Pour only. Show each value as a code: CodeText, CodeQR, CodeCODE39, CodeCODE128 or CodeJAN13
Option types

The type of an option says which functions take it:

Type Returned by Taken by
Option Every With function but WithCode NewText, NewPages and NewPour
PourOnlyOption WithCode NewPour
f, err := tm2.NewPour(
	tm2.Tape12mm,
	"URL",
	[]string{"https://example.com/"},
	tm2.WithCode(tm2.CodeQR),
)
Errors

Every error wraps one of these. Test it with errors.Is. Errors of the file system come back as they are, such as fs.ErrNotExist.

Error When
ErrInvalidOptions An option out of range, such as a margin under 1 mm
ErrCrashesApp A value the app crashes on, such as alignment 3. It is never written
ErrTapeNotSupported A tape width whose sizes are not known
ErrUnknownName A name ParseRotation, ParseCodeKind and the like do not know
ErrNoText No text, no values or pages, or one of blanks only
ErrBadText Text that is not UTF-8
ErrBadFile A file that is not a .tm2 file the package can read, or one it cannot encode
ErrOverLimit More rows, characters or columns than the app takes, or a label over 3000 mm
ErrNoRoom No room on the tape. Padding takes it, or there are too many lines, a line too long to run across, a font size too large, or a fixed length too short
ErrBadImage A picture that is not PNG, JPEG or GIF, or over 8192 by 8192 pixels
ErrBadCode A value the kind of code cannot hold, such as 13 digits for JAN-13
ErrBadPatch An operation Patch cannot apply, such as one that adds a key, or a patch that makes no .tm2 file
Reading files
  • ReadFile and ParseFile read a .tm2 file, from the app or from this package.
  • Drawer types the package does not know are kept as RawDrawer.
  • Keys it does not know, of the file, a document or a drawer, are kept in their Unknown field.
  • Writing the file back keeps both as they were.

License

tepra.tm2 is under the MIT License.

The mascot is a Go gopher holding a strip of label tape. The Go gopher was designed by Renée French, under CC BY 4.0.

Documentation

Overview

Package tm2 reads and writes .tm2 files, the labels of TEPRA LINK 2.

TEPRA LINK 2 is KING JIM's app for the "TEPRA" PRO label printers. A .tm2 file is one line of JSON. This package builds such files, so a label can be made elsewhere, opened in the app and printed from there. It does not talk to a printer.

The format is not documented. This package follows files the app wrote, and writes every key they have. The keys of an object come in the order of the fields of its type, not of those files.

Lengths are in points (1/72 inch), as in the file, unless a name says mm.

Index

Constants

View Source
const (
	DrawerTypeText  = "text"
	DrawerTypePour  = "pour"
	DrawerTypeImage = "image"
)

The drawer types this package knows.

View Source
const (
	PourMaxRows      = 1000
	PourMaxCellRunes = 1000
)

The limits of the app's pour data.

View Source
const (
	FontGothic     = "OTBGoStdR-Normal"
	FontGothicBold = "OTBGoStdB-Normal"
)

The fonts of TEPRA LINK 2, by the names the app writes.

View Source
const DefaultBorderPaddingMM = 1.5

DefaultBorderPaddingMM is the padding of a label with a border and no WithPaddingMM, in mm.

View Source
const DefaultBorderWidth = 0.7

DefaultBorderWidth is the width of a border as the app writes it. In the app, 0.35 showed thinner, and 1.4 and 2.8 wider.

View Source
const DefaultImageThreshold = 128

DefaultImageThreshold is the threshold of a picture of a template of the app.

View Source
const DefaultMarginMM = 1.0

DefaultMarginMM is the blank tape before and after a label as the app sets it, in mm.

View Source
const FileTableColumns = 50

FileTableColumns is how many columns the app writes in the table, used or not.

View Source
const FileVersion = "2.0.0"

FileVersion is the "version" TEPRA LINK 2 writes.

Variables

View Source
var (
	// ErrTapeNotSupported is a tape width whose sizes are not known.
	ErrTapeNotSupported = errors.New("tm2: tape width not supported")
	// ErrUnknownName is a name ParseFillMode, ParseBorderType, ParseAlign,
	// ParseVerticalAlign, ParseRotation, ParseCodeKind or ParseImageMode
	// does not know.
	ErrUnknownName = errors.New("tm2: unknown name")
	// ErrInvalidOptions is an Option, or options together, that NewText,
	// NewPages or NewPour cannot use.
	ErrInvalidOptions = errors.New("tm2: invalid options")
	// ErrCrashesApp is a value TEPRA LINK 2 crashes on. It is not written.
	ErrCrashesApp = errors.New("tm2: the app crashes on it")
	// ErrBadFile is a file that is not a .tm2 file this package can read, or
	// one it cannot encode. It wraps the JSON error.
	ErrBadFile = errors.New("tm2: bad .tm2 file")
	// ErrBadText is text that is not UTF-8, which a file cannot hold.
	ErrBadText = errors.New("tm2: text is not UTF-8")
	// ErrNoText is a label with no text: an empty text, or no values to
	// pour.
	ErrNoText = errors.New("tm2: no text")
	// ErrOverLimit is more than the app takes: rows, characters in a cell,
	// columns, or a label over 3000 mm.
	ErrOverLimit = errors.New("tm2: over the app's limit")
	// ErrNoRoom is no room on the tape for what is on a label: padding that
	// takes it, too many lines, a line too long to run across the tape, a
	// font size too large, or a fixed length too short.
	ErrNoRoom = errors.New("tm2: no room on the tape")
	// ErrBadImage is a picture that cannot be read as PNG, JPEG or GIF.
	ErrBadImage = errors.New("tm2: bad picture")
	// ErrBadCode is a value that cannot be shown as the kind of code asked
	// for.
	ErrBadCode = errors.New("tm2: bad value for a code")
	// ErrBadPatch is an operation File.Patch cannot apply, or a file the
	// operations make that is no .tm2 file.
	ErrBadPatch = errors.New("tm2: bad patch")
)

The errors of this package. Each error it returns wraps one or more of these, to test with errors.Is. Errors of the file system, and of a reader or a writer, are returned as they are, to test with errors.Is too.

View Source
var (
	Tape4mm  = Tape{WidthMM: 4, PrintableHeight: 8.8, FrameHeight: 12}
	Tape6mm  = Tape{WidthMM: 6, PrintableHeight: 14.400001, FrameHeight: 18}
	Tape9mm  = Tape{WidthMM: 9, PrintableHeight: 21.6, FrameHeight: 26}
	Tape12mm = Tape{WidthMM: 12, PrintableHeight: 28.800001, FrameHeight: 35}
	Tape18mm = Tape{WidthMM: 18, PrintableHeight: 43.2, FrameHeight: 52}
	Tape24mm = Tape{WidthMM: 24, PrintableHeight: 51.2, FrameHeight: 69}
	Tape36mm = Tape{WidthMM: 36, PrintableHeight: 76.8, FrameHeight: 103}
	Tape50mm = Tape{WidthMM: 50, PrintableHeight: 135.8, FrameHeight: 142}
)

The tapes whose sizes are known. Each one's sizes come from a file the app wrote for it, in testdata.

View Source
var (
	Black = Color{0, 0, 0, 1}
	White = Color{1, 1, 1, 1}
)

The colors the app writes for black text on a white tape.

Tapes are the tapes whose sizes are known, narrowest first. Other widths need a file the app wrote for them.

Functions

func MMToPoints

func MMToPoints(mm float64) float64

MMToPoints converts a length in mm to points.

func PointsToMM

func PointsToMM(pt float64) float64

PointsToMM converts a length in points to mm.

Types

type Align

type Align int

Align is where a text box puts each line across its frame. Each value was seen in TEPRA LINK 2 for Android, opening a file this package wrote. The app crashes on a file with 3.

const (
	AlignLeft   Align = 0
	AlignCenter Align = 1
	AlignRight  Align = 2
)

The alignments across.

func ParseAlign

func ParseAlign(name string) (Align, error)

ParseAlign returns the alignment of a name: left, center or right.

func (Align) String

func (a Align) String() string

String returns the name of a, as ParseAlign takes it.

func (Align) Valid

func (a Align) Valid() bool

Valid reports whether a is one of the alignments the app opens.

type BaseDrawer

type BaseDrawer struct {
	// Identifier is a UUID, unique in the file.
	Identifier string `json:"-"`

	// Rotate turns the drawer in Frame.
	Rotate Rotation `json:"Rotate"`
	// TapeForegroundColor is the color the app shows the text in, Black as
	// it writes it. White showed white text on the white tape.
	TapeForegroundColor Color `json:"tapeForegroundColor"`
	// Frame is where the drawer is in the document's frame. A text box fits
	// its text to it unless SizePriority is set. A picture fits in it,
	// keeping its shape, centred.
	Frame Rect `json:"frame"`
	// BIType is the line drawn on the edges of Frame.
	BIType BorderType `json:"BIType"`
	// BILineWidthValue is the width of the BIType line, DefaultBorderWidth
	// as the app writes it. It is spelled "BILineWidhValue" in the file.
	BILineWidthValue float64 `json:"BILineWidhValue"`

	// Below: written as the app writes them. Values tried showed no change
	// in the app, or none were tried.
	// TapeBackgroundColor: Black did not fill the box behind the text.
	TapeBackgroundColor Color `json:"tapeBackgroundColor"`
	// BILineThickness, BILineStyle and BILineWidth: thickness 1 to 3, style
	// 0 to 4 and width 0.5 to 2, with box and rounded borders.
	BILineThickness int     `json:"BILineThickness"`
	BILineStyle     int     `json:"BILineStyle"`
	BILineWidth     float64 `json:"BILineWidth"`
	// TapeVertical, TapeTapeFrame and FrameTop: set, and a frame of
	// [0, 0, 40, 20].
	TapeVertical  bool `json:"tapeVertical"`
	TapeTapeFrame Rect `json:"tapeTapeFrame"`
	FrameTop      bool `json:"frameTop"`

	// Unknown holds the keys this package does not know, as they were read,
	// and writes them back after the others. A newer app may write keys a
	// file read and written here must not lose.
	Unknown jsontext.Value `json:",embed"`
}

BaseDrawer holds the fields every drawer has.

func (*BaseDrawer) Base

func (b *BaseDrawer) Base() *BaseDrawer

Base returns b.

type BorderType

type BorderType int

BorderType is the line a drawer draws around its frame. Each type was seen in the app, opening a file this package wrote. Values from 6 up drew no line.

const (
	BorderNone      BorderType = 0
	BorderBox       BorderType = 1
	BorderRounded   BorderType = 2
	BorderTopBottom BorderType = 3
	BorderTop       BorderType = 4
	BorderBottom    BorderType = 5
)

The border types.

func ParseBorderType

func ParseBorderType(name string) (BorderType, error)

ParseBorderType returns the border type of a name: none, box, rounded, top-bottom, top or bottom.

func (BorderType) String

func (b BorderType) String() string

String returns the name of b, as ParseBorderType takes it.

func (BorderType) Valid

func (b BorderType) Valid() bool

Valid reports whether b is one of the border types known to draw.

type CodeKind

type CodeKind int

CodeKind is what a PourDrawer shows its column as: text, or a code made of it. 1 showed a QR code in the app, and 2 and 3 barcodes. That 2 and 3 are CODE39 and CODE128, and 4 JAN-13, follows the order of the app's manual.

const (
	CodeText    CodeKind = 0
	CodeQR      CodeKind = 1
	CodeCODE39  CodeKind = 2
	CodeCODE128 CodeKind = 3
	// CodeJAN13 takes 12 digits. The app adds the check digit.
	CodeJAN13 CodeKind = 4
)

The kinds of code.

func ParseCodeKind

func ParseCodeKind(name string) (CodeKind, error)

ParseCodeKind returns the kind of code of a name: text, qr, code39, code128 or jan13.

func (CodeKind) String

func (k CodeKind) String() string

String returns the name of k, as ParseCodeKind takes it.

func (CodeKind) Valid

func (k CodeKind) Valid() bool

Valid reports whether k is one of the kinds of code known.

type Color

type Color [4]float64

Color is red, green, blue and alpha, each from 0 to 1.

type Document

type Document struct {
	// Drawers are drawn in order, each over the ones before.
	Drawers Drawers `json:"drawers"`
	// Frame is the label without its margins. Its width is the label's
	// length, as the app showed it.
	Frame Rect `json:"frame"`
	// TapeWidthMM is the tape's width in mm. The app shows the label on a
	// tape of this width.
	TapeWidthMM int `json:"SettingsTapeWidth"`
	// PrintableArea is the height of the band the app prints on, in points.
	// It is the tape's PrintableHeight. A smaller value showed a smaller
	// band.
	PrintableArea float64 `json:"SettingsPrintableArea"`
	// AutoLength makes the label as long as Frame. Unset, the label is
	// FixedLength long.
	AutoLength  bool    `json:"SettingsAutoLength"`
	FixedLength float64 `json:"SettingsFixedLength"`
	// Margin is the blank tape before and after Frame, in points.
	Margin float64 `json:"SettingsMargin"`
	// ForegroundColor and BackgroundColor are the colors of the tape's ink
	// and of the tape, as the app shows the label. Swapped, the whole label
	// showed black.
	ForegroundColor Color `json:"SettingsForegroundColor"`
	BackgroundColor Color `json:"SettingsBackgroundColor"`
	// TapeVertical turns the whole label to run down the tape.
	TapeVertical bool `json:"SettingsTapeVertical"`
	// MultiplePage shows the app's controls for more than one page. The app
	// sets it on a pour label.
	MultiplePage bool `json:"MultiplePage"`
	// PourMode shows the label in the app's pour form (流し込み), filled
	// from the file's TableData. Unset, it is a plain label (一般).
	PourMode bool `json:"PourMode"`

	// Below: written as the app writes them. Values tried showed no change
	// in the app, or none were tried.
	// Name and PrintableFrame: another name, and half the width.
	Name                string `json:"name"`
	PrintableFrame      Rect   `json:"printableFrame"`
	Identifier          string `json:"identifier"`
	ForegroundColorName string `json:"SettingsForegroundColorName"`
	BackgroundColorName string `json:"SettingsBackgroundColorName"`

	// Unknown holds the keys this package does not know, as they were read,
	// and writes them back after the others. A newer app may write keys a
	// file read and written here must not lose.
	Unknown jsontext.Value `json:",embed"`
}

Document is one label of a file: the tape settings and its drawers.

func (*Document) LengthMM

func (d *Document) LengthMM() float64

LengthMM is the length of tape the label takes, margins included, in mm.

type Drawer

type Drawer interface {
	// DrawerType is the drawer's "type" in the file.
	DrawerType() string
	// Base returns the fields every drawer has.
	Base() *BaseDrawer
}

Drawer is an object on a label: a TextDrawer, PourDrawer, ImageDrawer, or a RawDrawer for a type this package does not know.

type Drawers

type Drawers []Drawer

Drawers are the objects of a Document, drawn in order.

func (Drawers) MarshalJSON

func (ds Drawers) MarshalJSON() ([]byte, error)

MarshalJSON is MarshalJSONTo, for encoding/json version 1. encoding/json escapes <, > and & in what it returns, which the app does not.

func (Drawers) MarshalJSONTo

func (ds Drawers) MarshalJSONTo(enc *jsontext.Encoder) error

MarshalJSONTo writes each drawer as the app does: "type", "identifier" and an empty key come first, then the drawer's fields.

func (*Drawers) UnmarshalJSON

func (ds *Drawers) UnmarshalJSON(data []byte) error

UnmarshalJSON is UnmarshalJSONFrom, for encoding/json version 1.

func (*Drawers) UnmarshalJSONFrom

func (ds *Drawers) UnmarshalJSONFrom(dec *jsontext.Decoder) error

UnmarshalJSONFrom reads drawers by their "type". An unknown type becomes a RawDrawer.

type File

type File struct {
	// Documents are the pages of the file, a label each. The app lists them
	// when the first has MultiplePage set, and prints them together.
	Documents []Document `json:"documents"`
	// CurrentPage is the document the app opens, from 0. The app crashes on
	// a file whose CurrentPage has no document.
	CurrentPage int `json:"currentPage"`
	// FileName is the name the app shows the label by, with ".tm2". It is
	// not the name of the file the app opened.
	FileName string `json:"fileName"`
	// TableData is the data a PourDrawer fills from: one row, and one label,
	// per value, of FileTableColumns cells each.
	TableData [][]string `json:"tableData"`
	// TableHeader is the title of each column of TableData, shown in the
	// app's pour data editor.
	TableHeader []string `json:"tableHeader"`

	// Below: written as the app writes them. Values tried showed no change
	// in the app, or none were tried.
	// SavedLength and Version: 999 or left out, and "1.0.0". Date,
	// TextWords, Category, Keywords and the catalog titles do not show where
	// the app edits a label.
	SavedLength    *float64 `json:"savedLength,omitzero"`
	Version        string   `json:"version"`
	Date           string   `json:"date"`
	TextWords      string   `json:"textWords"`
	Category       string   `json:"category"`
	Keywords       string   `json:"keywords"`
	CatalogTitle   string   `json:"CatalogTitle"`
	CatalogTitleEN string   `json:"CatalogTitleEN"`
	KeywordsEN     string   `json:"keywordsEN"`

	// Unknown holds the keys this package does not know, as they were read,
	// and writes them back after the others. A newer app may write keys a
	// file read and written here must not lose.
	Unknown jsontext.Value `json:",embed"`
}

File is a .tm2 file.

func NewPages

func NewPages(tape Tape, texts []string, opts ...TextOption) (*File, error)

NewPages returns a file of one page per text, each laid out as NewText lays out its label. So each label has a font size and a length of its own, unlike the labels of NewPour. The app lists the pages, and prints them together. A text may hold line breaks ("\n").

func NewPour

func NewPour(tape Tape, column string, values []string, opts ...PourOption) (*File, error)

NewPour returns a file that prints one label per value, with the column titled column. A value may hold line breaks ("\n"). All the labels share one frame, sized for the longest value.

Use NewPour for codes (WithCode). For a list of text, NewPages with WithLengthMM lays the labels out better: the app shows poured text at the left of its frame whatever WithAlign says, and inverted fill only behind the letters.

Inverted text of more than one line is poured from a column per line: column, then column 2, column 3 and on.

The text keeps its font size on every label. The app would otherwise fit each value to the shared frame: a value of fewer lines would grow to its height, and run past its sides.

func NewText

func NewText(tape Tape, text string, opts ...TextOption) (*File, error)

NewText returns a file of one label that prints text. text may hold line breaks ("\n").

func ParseFile

func ParseFile(r io.Reader) (*File, error)

ParseFile reads a .tm2 file from r.

func ReadFile

func ReadFile(path string) (*File, error)

ReadFile reads the .tm2 file at path.

func (*File) MarshalJSON

func (f *File) MarshalJSON() ([]byte, error)

MarshalJSON is MarshalJSONTo, for encoding/json version 1. encoding/json escapes <, > and & in what it returns, which the app does not.

func (*File) MarshalJSONTo

func (f *File) MarshalJSONTo(enc *jsontext.Encoder) error

MarshalJSONTo writes f, unless the app would crash on it.

func (*File) Patch added in v0.4.0

func (f *File) Patch(ops ...PatchOp) error

Patch applies ops to f in order, as a JSON Patch (RFC 6902) on the file as WriteTo writes it. Either every operation applies, or f is left as it was.

It keeps to what the app writes:

  • A key is not added to an object, nor removed from one. The app writes every key, so a key's value is replaced instead. Items of an array are added and removed freely.
  • An object put in place of the file, a document or a drawer, by any operation, has every key tm2 writes for it, and no other key but those the file had there. So a drawer's "type" changes only with its keys. A drawer of a type tm2 does not know is one the file had. It may move, but not be copied: it is written as it was read, so its identifier cannot change.
  • A drawer added to a document's drawers starts as the app sets a new one of its "type" (text, pour or image), in the document's frame. The keys given replace its values. A key it does not have is an error.
  • The empty key after a drawer's identifier stays as the app writes it.
  • A document or a drawer with no identifier, or one that another before it has, as a copy has, gets a new one.
  • A text box with text shows it, not its placeholder. A box with no text keeps its HasPlaceholder: tm2's own border box is empty, with no placeholder.
  • With more than one document, each has MultiplePage set, as NewPages sets it: the app lists the pages only then. A CurrentPage past the last document is the last.
  • Each row of tableData, and tableHeader, gets empty cells up to FileTableColumns.
  • A picture the patch gives is checked as NewText checks an icon. It may be a JPEG or a GIF, and is made a PNG, as the app stores pictures.

Patch does not lay the label out again. A drawer moved or a text made longer keeps the frames it was given.

func (*File) WriteFile

func (f *File) WriteFile(path string) error

WriteFile writes f to path, replacing a file there.

func (*File) WriteTo

func (f *File) WriteTo(w io.Writer) (int64, error)

WriteTo writes f to w as a .tm2 file: one line of JSON, with <, > and & as they are, as the app writes them.

type FillMode

type FillMode int

FillMode is how a text box fills the box behind its text. Each mode was seen in TEPRA LINK 2 for Android, opening a file this package wrote. The app crashes on a file with any other value, from 3 up.

const (
	// FillNone is black text on the tape.
	FillNone FillMode = 0
	// FillInverted is white text on a black box the size of the frame. The
	// app shows only the last line of such a box, so NewPour and NewText
	// give each line a box of its own.
	FillInverted FillMode = 1
	// FillShaded is black text on a light, dotted box the size of the frame.
	FillShaded FillMode = 2
)

The fill modes.

func ParseFillMode

func ParseFillMode(name string) (FillMode, error)

ParseFillMode returns the fill mode of a name: none, inverted or shaded.

func (FillMode) String

func (m FillMode) String() string

String returns the name of m, as ParseFillMode takes it.

func (FillMode) Valid

func (m FillMode) Valid() bool

Valid reports whether m is one of the fill modes the app opens.

type ImageDrawer

type ImageDrawer struct {
	BaseDrawer

	// Image is a PNG, base64 in the file. The app fits it in Frame, keeping
	// its shape, centred.
	Image []byte `json:"image"`
	// ImageKind is 3 as the app writes it. 1 showed the picture in grey,
	// not turned to black and white. 0 and 2 showed no change.
	ImageKind int `json:"imageKind"`
	// ImageMode is how the picture turns to black and white.
	ImageMode ImageMode `json:"imageMode"`
	// ImageThreshold is the grey level, from 0 to 255, below which a pixel
	// is black, with ImageModeThreshold.
	ImageThreshold int `json:"imageThreshold"`

	// Below: written as the app writes them. Values tried showed no change
	// in the app, or none were tried.
	// ImageBlock and ImageOffset: 50, and 0.
	ImageBlock  int `json:"imageBlock"`
	ImageOffset int `json:"imageOffset"`
}

ImageDrawer is a picture.

func NewImageDrawer

func NewImageDrawer(png []byte, frame Rect) *ImageDrawer

NewImageDrawer returns a picture in frame, set as in a file the app wrote. The app fits png in frame, keeping its shape, centred. It turns it to black and white at ImageThreshold.

func (*ImageDrawer) DrawerType

func (*ImageDrawer) DrawerType() string

DrawerType returns DrawerTypeImage.

type ImageMode

type ImageMode int

ImageMode is how the app turns a picture to black and white. Each mode was seen in the app, opening a file this package wrote. 0 and 4 showed as ImageModeThreshold does.

const (
	// ImageModeDiffusion spreads the error of each pixel to the next ones:
	// grey shows as scattered dots.
	ImageModeDiffusion ImageMode = 1
	// ImageModeThreshold makes each pixel black below ImageThreshold. It is
	// the mode of a picture of a template of the app.
	ImageModeThreshold ImageMode = 2
	// ImageModeScreen shows grey as a regular screen of dots.
	ImageModeScreen ImageMode = 3
)

The modes the app showed differently.

func ParseImageMode

func ParseImageMode(name string) (ImageMode, error)

ParseImageMode returns the mode of a name: diffusion, threshold or screen.

func (ImageMode) String

func (m ImageMode) String() string

String returns the name of m, as ParseImageMode takes it.

func (ImageMode) Valid

func (m ImageMode) Valid() bool

Valid reports whether m is one of the modes known.

type Option

type Option func(*optionConfig)

Option sets something every kind of label has. NewText, NewPages and NewPour all take it: it is a TextOption and a PourOption. Each With function returns one, but WithCode. What no option sets is as the app sets it.

func WithAlign

func WithAlign(a Align) Option

WithAlign sets where each line of text goes across its frame. It is AlignLeft by default, as the app sets it.

func WithBackground

func WithBackground(picture []byte) Option

WithBackground stretches a PNG, JPEG or GIF picture under the whole label.

func WithBold

func WithBold() Option

WithBold writes the text in FontGothicBold.

func WithBorder

func WithBorder(b BorderType) Option

WithBorder draws a line around the label, on a box of its own. The text keeps DefaultBorderPaddingMM from it, unless WithPaddingMM is given.

func WithBorderWidth

func WithBorderWidth(w float64) Option

WithBorderWidth sets the width of the border. It is DefaultBorderWidth by default.

func WithFill

func WithFill(m FillMode) Option

WithFill sets the box behind the text.

func WithFontSize

func WithFontSize(pt float64) Option

WithFontSize sets the size of the text, in points. By default it is the size at which the text fills the tape.

func WithIcon

func WithIcon(picture []byte) Option

WithIcon puts a PNG, JPEG or GIF picture before the text, as high as the tape prints, keeping its shape.

func WithImageMode

func WithImageMode(m ImageMode) Option

WithImageMode sets how the app turns the icon and the background to black and white. It is ImageModeThreshold by default.

func WithImageThreshold

func WithImageThreshold(level int) Option

WithImageThreshold sets the grey level, from 0 to 255, below which a pixel of the icon and the background is black, with ImageModeThreshold. It is DefaultImageThreshold by default.

func WithLengthMM

func WithLengthMM(mm float64) Option

WithLengthMM makes the label this long, margins included, in mm, from 10 to 3000 as the app takes it. By default the label is as long as what is on it. Text that does not fit gets smaller, unless WithFontSize is given, and what is on the label is centred.

func WithMarginMM

func WithMarginMM(mm float64) Option

WithMarginMM sets the blank tape before and after the label, in mm, from 1 to 500 as the app takes it. It is DefaultMarginMM by default.

func WithName

func WithName(name string) Option

WithName names the file in the app, without ".tm2". It is "label" by default.

func WithPaddingMM

func WithPaddingMM(mm float64) Option

WithPaddingMM sets the blank between the label's edges and what is on it, in mm: room for a border, or for the frame of a background.

func WithRotation

func WithRotation(r Rotation) Option

WithRotation turns the text. Rotation90 and Rotation270 run its lines across the tape.

func WithTime

func WithTime(t time.Time) Option

WithTime sets the file's date. It is the time of NewPour or NewText by default.

func WithVertical

func WithVertical() Option

WithVertical writes the text top to bottom, each line to the left of the one before. Its lines run across the tape, as with Rotation90.

func WithVerticalAlign

func WithVerticalAlign(a VerticalAlign) Option

WithVerticalAlign sets where the text goes down its frame. It is VerticalAlignMiddle by default, as the app sets it.

type PatchOp added in v0.4.0

type PatchOp struct {
	// Op is add, remove, replace, move, copy or test.
	Op   string `json:"op"`
	Path string `json:"path"`
	// From is the value that move and copy take.
	From string `json:"from,omitzero"`
	// Value is the value that add, replace and test take.
	Value jsontext.Value `json:"value,omitzero"`
}

PatchOp is one operation of a JSON Patch (RFC 6902), as File.Patch applies it. Path and From are JSON Pointers (RFC 6901) into the file as WriteTo writes it, such as "/documents/0/drawers/1/TIText".

type PourDrawer

type PourDrawer struct {
	TextDrawer

	// ColumnNumber is the column of the file's TableData the box shows, from
	// 0.
	ColumnNumber int `json:"ColumnNumber"`
	// Attribute is what the column shows as: text, or a code made of it.
	Attribute CodeKind `json:"Attribute"`
}

PourDrawer is a text box filled from a column of the file's table, one label per row.

func NewPourDrawer

func NewPourDrawer(column int, text string, frame Rect) *PourDrawer

NewPourDrawer returns a text box in frame for column, showing text in the editor.

func (*PourDrawer) DrawerType

func (*PourDrawer) DrawerType() string

DrawerType returns DrawerTypePour.

type PourOnlyOption

type PourOnlyOption func(*optionConfig)

PourOnlyOption sets what only the labels of NewPour have. It is not a TextOption, so NewText and NewPages do not compile with it.

func WithCode

func WithCode(k CodeKind) PourOnlyOption

WithCode shows each value of NewPour as a code instead of text. The app shows codes in pour data only, so NewText and NewPages do not take it.

type PourOption

type PourOption interface {
	// contains filtered or unexported methods
}

PourOption sets something of the labels NewPour makes. An Option is one, and so is a PourOnlyOption.

type RawDrawer

type RawDrawer struct {
	// BaseDrawer holds the fields every drawer has, as read. Changing them
	// does not change what is written.
	BaseDrawer

	// Type is the drawer's "type".
	Type string
	// JSON is the drawer as read.
	JSON jsontext.Value
}

RawDrawer is a drawer of a type this package does not know. It is written back as it was read.

func (*RawDrawer) DrawerType

func (r *RawDrawer) DrawerType() string

DrawerType returns r.Type.

type Rect

type Rect [4]float64

Rect is a frame: x, y, width and height, in points. y grows down the tape.

type Rotation

type Rotation int

Rotation turns a drawer in its frame, by a quarter turn or a half turn. Each value was seen in TEPRA LINK 2 for Android, opening a file this package wrote. The app crashes on a file with 90, and so on any value it does not know.

const (
	RotationNone Rotation = 0
	Rotation180  Rotation = 1
	// Rotation270 turns the text a quarter turn left: it reads bottom to
	// top.
	Rotation270 Rotation = 2
	// Rotation90 turns the text a quarter turn right: it reads top to
	// bottom.
	Rotation90 Rotation = 3
)

The rotations, clockwise.

func ParseRotation

func ParseRotation(name string) (Rotation, error)

ParseRotation returns the rotation of a name, in degrees clockwise: 0, 90, 180 or 270.

func (Rotation) String

func (r Rotation) String() string

String returns the name of r, as ParseRotation takes it.

func (Rotation) Valid

func (r Rotation) Valid() bool

Valid reports whether r is one of the rotations the app opens.

type Tape

type Tape struct {
	// WidthMM is the tape's width in mm, as in SettingsTapeWidth.
	WidthMM int
	// PrintableHeight is the height the printer can print on, in points.
	PrintableHeight float64
	// FrameHeight is the height of the label's frame, in points. The
	// printable band sits in its middle.
	FrameHeight float64
}

Tape is a tape width and the sizes the app writes for it.

func LookupTape

func LookupTape(widthMM int) (Tape, error)

LookupTape returns the tape of a width in mm.

func (Tape) PrintableTop

func (t Tape) PrintableTop() float64

PrintableTop is the y of the printable band in the frame, in points.

type TextDrawer

type TextDrawer struct {
	BaseDrawer

	// Text is what the box shows. "\n" breaks a line.
	Text string `json:"TIText"`
	// FontName is FontGothic or FontGothicBold. Other fonts were not tried.
	FontName string `json:"TIFontName"`
	// FontSize is the size of the text, in points. The app uses it only with
	// SizePriority. Otherwise it fits the text to Frame.
	FontSize float64 `json:"TIFontSize"`
	// Alignment is where each line goes across Frame.
	Alignment Align `json:"TIAlignment"`
	// VerticalAlignment is where the lines go down Frame.
	VerticalAlignment VerticalAlign `json:"TIVerticalAlignment"`
	// FillMode is the box behind the text.
	FillMode FillMode `json:"TIFillMode"`
	// FontFace is 1 as the app writes it. 0 showed no change. The app
	// crashes on 2, so other values are not written.
	FontFace int `json:"TIFontFace"`
	// TextVertical writes the lines top to bottom, each to the left of the
	// one before.
	TextVertical bool `json:"textVertical"`
	// HasPlaceholder shows "未入力のテキストボックス" in grey instead of
	// Text. The app sets it on a box with no text.
	HasPlaceholder bool `json:"hasPlaceholder"`
	// HoldAspect, set as the app sets it, fits the text to Frame, unless
	// SizePriority is set. Unset, the text keeps FontSize, its lines close
	// up, and the app marks the box 固.
	HoldAspect bool `json:"holdAspect"`
	// SizePriority keeps FontSize instead of fitting the text to Frame.
	SizePriority bool `json:"sizePriority"`

	// Below: written as the app writes them. Values tried showed no change
	// in the app, or none were tried.
	// Color: grey, red and white. TapeForegroundColor is the color shown.
	Color Color `json:"TIColor"`
	// Bold and Italic: set. FontGothicBold is how the app writes bold.
	Bold   bool `json:"TIBold"`
	Italic bool `json:"TIItalic"`
	// LineBreak: 0, 1 and 3, on text of two lines broken by "\n".
	LineBreak int `json:"TILineBreak"`
	// TextMargin: up to [3, 3], fitted to Frame and with SizePriority.
	TextMargin [2]float64 `json:"textMargin"`
}

TextDrawer is a text box.

func NewTextDrawer

func NewTextDrawer(text string, frame Rect) *TextDrawer

NewTextDrawer returns a text box in frame, set as the app sets a new one.

func (*TextDrawer) DrawerType

func (*TextDrawer) DrawerType() string

DrawerType returns DrawerTypeText.

type TextOption

type TextOption interface {
	// contains filtered or unexported methods
}

TextOption sets something of the labels NewText and NewPages make. An Option is one.

type VerticalAlign

type VerticalAlign int

VerticalAlign is where a text box puts its lines down its frame. Each value was seen in the app, opening a file this package wrote. The app opened 3, and showed it as VerticalAlignMiddle, so it is not offered.

const (
	VerticalAlignTop    VerticalAlign = 0
	VerticalAlignMiddle VerticalAlign = 1
	VerticalAlignBottom VerticalAlign = 2
)

The alignments down.

func ParseVerticalAlign

func ParseVerticalAlign(name string) (VerticalAlign, error)

ParseVerticalAlign returns the alignment of a name: top, middle or bottom.

func (VerticalAlign) String

func (a VerticalAlign) String() string

String returns the name of a, as ParseVerticalAlign takes it.

func (VerticalAlign) Valid

func (a VerticalAlign) Valid() bool

Valid reports whether a is one of the alignments seen in the app.

Directories

Path Synopsis
cmd
tm2 command
Command tm2 makes .tm2 label files for TEPRA LINK 2.
Command tm2 makes .tm2 label files for TEPRA LINK 2.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL