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
6 changes: 3 additions & 3 deletions GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -370,8 +370,8 @@ d.layout("C-101", { paper: "ARCH D" }, (sheet) => {
- Inside `layout`, every length is on the paper, in the paper's units: inches for every paper
tsdraft has. A text 1/8 inch high has `height: 0.125`. `sheet.width` and `sheet.height` are
the paper's size, and its lower-left corner is `[0, 0]`.
- The papers are `ARCH A` to `ARCH D` and `ANSI A` to `ANSI D`, each landscape and full
bleed. `ARCH D` is 36 by 24.
- The papers are `ARCH A` to `ARCH E` and `ANSI A` to `ANSI D`, each landscape and full
bleed. `ARCH D` is 36 by 24, and `ARCH E` 48 by 36.
- `sheet.viewport(corner, width, height, { center, ratio })` shows model space in a rectangle
on the paper. `center` is the model point at its middle. `ratio` is the one you give
`fromPaper`: 120 is 1" = 10'.
Expand All @@ -381,7 +381,7 @@ d.layout("C-101", { paper: "ARCH D" }, (sheet) => {
pattern times it, in every viewport. The picture of model space draws the same dashes that
many drawing units long, often too short to see, so judge linetypes on the sheet's picture.
- The sheet plots in black with `monochrome.ctb`. Pass `plotStyle: "acad.ctb"` to plot each
layer in its color.
layer in its color, or `"Grayscale.ctb"` in grays. `PLOT_STYLE_TABLES` lists them.
- Define blocks outside `layout`, and insert them inside it. An `id` is unique across model
space, blocks and every layout.
- A title block is a block with an attribute for each field, and a firm's own border is an
Expand Down
39 changes: 30 additions & 9 deletions docs/layouts.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,19 +45,27 @@ puts entities on a layer as it does anywhere.
### Paper

`paper` is one of `PAPERS`. Each is a size that AutoCAD's `DWG To PDF.pc3` offers as full
bleed, with no margin the plotter keeps clear, and landscape.
bleed, with no margin the plotter keeps clear, and a layout of each is landscape, with the
longer side across.

| Paper | Inches |
| -------- | --------- |
| `ARCH A` | 12 by 9 |
| `ARCH B` | 18 by 12 |
| `ARCH C` | 24 by 18 |
| `ARCH D` | 36 by 24 |
| `ARCH E` | 48 by 36 |
| `ANSI A` | 11 by 8.5 |
| `ANSI B` | 17 by 11 |
| `ANSI C` | 22 by 17 |
| `ANSI D` | 34 by 22 |

The plotter holds `ARCH E` upright, as `ARCH_full_bleed_E_(36.00_x_48.00_Inches)`, 36 wide
and 48 tall. Its page setup stores that size and turns the plot a quarter turn onto it, as
AutoCAD's own landscape page setup on that paper does, and the PDF shows the page landscape,
48 by 36, with the drawing upright. `PaperInfo.medium` holds the size as the plotter holds it
and the turn.

The paper's units are the units of the sheet: on these, an inch. The sheet's lower-left corner
is `[0, 0]`. Sizes drawn on a sheet are the sizes they plot at, so a text 1/8 inch high has a
height of `0.125`, whatever the drawing's own units are.
Expand All @@ -76,13 +84,25 @@ Every layout has the same page setup, apart from its paper and its plot style ta
| Plotter | `DWG To PDF.pc3` |
| What to plot | The layout |
| Scale | 1:1 |
| Plot style table | `monochrome.ctb`, or `acad.ctb` |
| Plot style table | One of `PLOT_STYLE_TABLES` |
| Lineweights | Plotted, each line as wide as its lineweight |
| Orientation | Landscape, as the paper is |
| Orientation | Landscape |

`plotStyle` is one of `PLOT_STYLE_TABLES`, the color-dependent tables AutoCAD installs. Each
plots a line as wide as its lineweight, apart from `DWF Virtual Pens.ctb`:

| Table | Colors |
| ---------------------- | ---------------------------------------------------------------- |
| `monochrome.ctb` | Every color in black. The default |
| `acad.ctb` | Each color in its own, and 7 in black |
| `Grayscale.ctb` | Each color in a gray of its own, and 7 in black |
| `DWF Virtual Pens.ctb` | Each color in the color of its pen, and every line 0.254 mm wide |

`plotStyle` is `"monochrome.ctb"` by default, which plots every color in black. With
`"acad.ctb"` each layer plots in its own color. AutoCAD plots a layout whose plot style table
it does not have with no table, each pen in its own color.
A pen of `DWF Virtual Pens.ctb` has a color of its own, which is near its index's but not
always the same: 9 plots as `#c0c0c0`, and 12 as `#a50000`. The table also gives every pen one
lineweight, so a line plots 0.254 mm wide whatever its own lineweight, and so does a viewport's
border. `toSVG` draws a sheet in the colors and widths its table plots. AutoCAD plots a layout
whose plot style table it does not have with no table, each pen in its own color.

### Names

Expand Down Expand Up @@ -186,10 +206,11 @@ set of ids.
no clip.
- A viewport `lint` reports an error for is drawn as its border alone.
- Every line is as wide as its lineweight on the paper, inside a viewport too, and dashes are
as long as they plot.
as long as they plot. Under `DWF Virtual Pens.ctb` every line is 0.254 mm wide.
- Colors are the ones the plot style table plots: black for `monochrome.ctb`.
- A viewport's border is drawn, as the thinnest line, when its layer is on, thawed and set to
plot. With `drawNoPlot` it is drawn on a layer that does not plot too.
- A viewport's border is drawn, as the thinnest line or 0.254 mm wide under
`DWF Virtual Pens.ctb`, when its layer is on, thawed and set to plot. With `drawNoPlot` it
is drawn on a layer that does not plot too.

Without `layout`, `toSVG` draws model space as it always has.

Expand Down
6 changes: 3 additions & 3 deletions docs/rules.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,9 @@ it would take `1e+100` for `1e+10` and report nothing.
tab. See [Names](layouts.md#names).
- No two layouts have names AutoCAD takes for one, as `Sheet` and `SHEET` are. AutoCAD keeps
one of the two, and its `AUDIT` reports the other as missing from the dictionary of layouts.
- A layout's paper is one of `PAPERS`, and its plot style table `monochrome.ctb` or
`acad.ctb`. AutoCAD plots nothing for a layout whose paper the plotter knows neither by
name nor by size, and plots one whose plot style table it does not have with no table.
- A layout's paper is one of `PAPERS`, and its plot style table one of `PLOT_STYLE_TABLES`.
AutoCAD plots nothing for a layout whose paper the plotter knows neither by name nor by
size, and plots one whose plot style table it does not have with no table.
- A viewport's corner and center are points, its width and height are sizes, and its ratio is
greater than 0. The height of model space it shows, which a file holds in place of a
scale, is not written as 0 and is under 1e100.
Expand Down
17 changes: 9 additions & 8 deletions src/dxf-r2018.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
import {
DEFAULT_PLOT_STYLE_TABLE,
fromMillimetres,
mediumMargins,
paperInfo,
paperMillimetres,
PLOTTER,
Expand Down Expand Up @@ -1348,22 +1349,22 @@ function writeLayout(
box: readonly [number, number, number, number],
): void {
const { layout, paper, handles } = sheet;
const [left, bottom, right, top] = paper.printable;
const mm = (length: number): number => paperMillimetres(length, paper.units);
const [width, height] = [mm(paper.width), mm(paper.height)];
const [left, bottom, right, top] = mediumMargins(paper);
g(0, "LAYOUT");
ownedBy(g, handles.layout, dictionary);
g(100, "AcDbPlotSettings");
g(1, ""); // page setup name
g(2, PLOTTER);
g(4, paper.media);
g(6, ""); // plot view
g(40, mm(left)); // the margins the plotter keeps clear
// The margins the plotter keeps clear and the medium's size, as the plotter holds it.
g(40, mm(left));
g(41, mm(bottom));
g(42, mm(paper.width - right));
g(43, mm(paper.height - top));
g(44, width);
g(45, height);
g(42, mm(right));
g(43, mm(top));
g(44, mm(paper.medium.width));
g(45, mm(paper.medium.height));
g(46, 0); // plot origin
g(47, 0);
g(48, 0); // plot window, lower left
Expand All @@ -1374,7 +1375,7 @@ function writeLayout(
g(143, 1); // custom scale: drawing units
g(70, PLOT_VIEWPORTS_FIRST | PLOT_LINEWEIGHTS | PLOT_PLOT_STYLES | PLOT_USE_STANDARD_SCALE);
g(72, paper.units === "in" ? 0 : 1);
g(73, 0); // rotation: none, the paper is landscape as it is
g(73, paper.medium.rotation); // the plot's rotation onto the medium
g(74, 5); // plot area: the layout
g(7, layout.plotStyle ?? DEFAULT_PLOT_STYLE_TABLE);
g(75, 16); // standard scale: 1:1
Expand Down
8 changes: 7 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,13 @@ export { DrawingError, lint, type Diagnostic, type LintOptions, type LintRule }
export { CENTER, DASHDOT, DASHED, DOT, HIDDEN, LINEWEIGHTS, PHANTOM } from "./linetypes.ts";
export { measureText, type TextMeasure, type TextToMeasure } from "./measure.ts";
export { fromPaper, type PaperScale, type PaperUnit } from "./paper.ts";
export { PAPERS, type Paper, type PaperInfo, type PlotStyleTable } from "./papers.ts";
export {
PAPERS,
PLOT_STYLE_TABLES,
type Paper,
type PaperInfo,
type PlotStyleTable,
} from "./papers.ts";
export type {
Aci,
ArrowheadOf,
Expand Down
55 changes: 47 additions & 8 deletions src/papers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,20 @@ export interface PaperInfo {
readonly media: string;
/** The unit of the size, and of everything drawn on a layout of this paper. */
readonly units: PaperUnit;
/** The width of the sheet, which is its longer side. */
/** The width of a layout of this paper, which is its longer side. */
readonly width: number;
readonly height: number;
/**
* The medium as the plotter holds it, which the page setup stores: its width and height, and
* the plot's rotation on it, as DXF group 73 holds it. 0 plots the layout as it is, on a medium
* as wide as the layout. 1 turns it a quarter turn onto a medium held upright, as AutoCAD's own
* landscape page setup on that medium does, and the PDF shows the page turned back, landscape.
*/
readonly medium: {
readonly width: number;
readonly height: number;
readonly rotation: 0 | 1;
};
/**
* The part of the sheet the plotter prints on, as its lower-left and upper-right corners
* from the sheet's lower-left corner: `[left, bottom, right, top]`. A full-bleed size prints
Expand All @@ -21,27 +32,33 @@ export interface PaperInfo {

/**
* Every paper a layout may have. Each is a size that AutoCAD's `DWG To PDF.pc3` offers as full
* bleed, with no margin the plotter keeps clear, and landscape, with the longer side across.
* The list is closed because a page setup names its paper by the name the plotter gives it,
* and AutoCAD plots a layout whose paper the plotter does not have on another size.
* bleed, with no margin the plotter keeps clear, and a layout of each is landscape, with the
* longer side across. The plotter holds `ARCH E` upright, so its plot is turned a quarter turn
* onto it. The list is closed because a page setup names its paper by the name the plotter
* gives it, and AutoCAD plots a layout whose paper the plotter does not have on another size.
*/
export const PAPERS = {
"ARCH A": inches("ARCH_full_bleed_A_(12.00_x_9.00_Inches)", 12, 9),
"ARCH B": inches("ARCH_full_bleed_B_(18.00_x_12.00_Inches)", 18, 12),
"ARCH C": inches("ARCH_full_bleed_C_(24.00_x_18.00_Inches)", 24, 18),
"ARCH D": inches("ARCH_full_bleed_D_(36.00_x_24.00_Inches)", 36, 24),
"ARCH E": inches("ARCH_full_bleed_E_(36.00_x_48.00_Inches)", 48, 36, 1),
"ANSI A": inches("ANSI_full_bleed_A_(11.00_x_8.50_Inches)", 11, 8.5),
"ANSI B": inches("ANSI_full_bleed_B_(17.00_x_11.00_Inches)", 17, 11),
"ANSI C": inches("ANSI_full_bleed_C_(22.00_x_17.00_Inches)", 22, 17),
"ANSI D": inches("ANSI_full_bleed_D_(34.00_x_22.00_Inches)", 34, 22),
} as const satisfies Readonly<Record<string, PaperInfo>>;

/** A paper in inches, `width` across the layout, on a medium the plot turns `rotation` onto. */
function inches<M extends string, W extends number, H extends number>(
media: M,
width: W,
height: H,
rotation: 0 | 1 = 0,
) {
return { media, units: "in", width, height, printable: [0, 0, width, height] } as const;
const medium =
rotation === 0 ? { width, height, rotation } : { width: height, height: width, rotation };
return { media, units: "in", width, height, medium, printable: [0, 0, width, height] } as const;
}

/** The name of a paper a layout may have. */
Expand All @@ -54,10 +71,17 @@ export function paperInfo(name: string): PaperInfo | undefined {

/**
* The plot style tables a layout's page setup may name, which are color-dependent tables that
* AutoCAD installs. `monochrome.ctb` plots every color in black, and `acad.ctb` plots each in
* its own color. Both plot a line at the lineweight it has.
* AutoCAD installs. `monochrome.ctb` plots every color in black, `acad.ctb` each in its own
* color, `Grayscale.ctb` each in a gray of its own, and `DWF Virtual Pens.ctb` each in the color
* of its pen. Each but `DWF Virtual Pens.ctb` plots a line at the lineweight it has; that one
* plots every line 0.254 mm wide.
*/
export const PLOT_STYLE_TABLES = ["monochrome.ctb", "acad.ctb"] as const;
export const PLOT_STYLE_TABLES = [
"monochrome.ctb",
"acad.ctb",
"Grayscale.ctb",
"DWF Virtual Pens.ctb",
] as const;

/** The name of a plot style table a layout may have. */
export type PlotStyleTable = (typeof PLOT_STYLE_TABLES)[number];
Expand All @@ -78,6 +102,21 @@ export function paperMillimetres(length: number, units: PaperUnit): number {
return Math.fround(units === "in" ? length * MM_PER_INCH : length);
}

/**
* The strip the plotter keeps clear at each edge of the medium, `[left, bottom, right, top]` in
* the paper's units, as the page setup holds them: in the medium's own orientation. A plot
* turned onto a medium held upright puts the layout's bottom edge on the medium's left and the
* layout's left edge at the medium's top.
*/
export function mediumMargins(
paper: PaperInfo,
): readonly [left: number, bottom: number, right: number, top: number] {
const [left, bottom, right, top] = paper.printable;
const margins = [left, bottom, paper.width - right, paper.height - top] as const;
if (paper.medium.rotation === 0) return margins;
return [margins[1], margins[2], margins[3], margins[0]];
}

/** A length a page setup holds in millimetres, in the paper's units. */
export function fromMillimetres(length: number, units: PaperUnit): number {
return units === "in" ? length / MM_PER_INCH : length;
Expand Down
4 changes: 2 additions & 2 deletions src/rules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,9 +150,9 @@
const LAYOUT_NAME_MODEL =
"A layout cannot be named Model, in any case of its letters. AutoCAD keeps that name for the model tab: it discards a drawing whose layout is named MODEL, takes a layout named model for the model tab's own and loses its sheet, and never finishes opening a drawing with a second layout named Model";
const PAPER =
'A paper must be one of PAPERS, the full-bleed landscape sizes of AutoCAD\'s DWG To PDF.pc3, such as "ARCH D". A page setup names its paper as the plotter does, and AutoCAD plots nothing for a layout whose paper the plotter knows neither by its name nor by its size';
'A paper must be one of PAPERS, the full-bleed sizes of AutoCAD\'s DWG To PDF.pc3, such as "ARCH D", each laid out landscape. A page setup names its paper as the plotter does, and AutoCAD plots nothing for a layout whose paper the plotter knows neither by its name nor by its size';
const PLOT_STYLE =
'A plot style table must be "monochrome.ctb" or "acad.ctb", which AutoCAD installs. AutoCAD plots a layout whose plot style table it does not have with no table, each pen in its own color';
'A plot style table must be "monochrome.ctb", "acad.ctb", "Grayscale.ctb" or "DWF Virtual Pens.ctb", which AutoCAD installs. AutoCAD plots a layout whose plot style table it does not have with no table, each pen in its own color';
const XREF_PATH_EMPTY =
"An xref's path cannot be empty. AutoCAD then looks for a DWG file named as the xref is";
const XREF_PATH_DXF =
Expand Down Expand Up @@ -1271,7 +1271,7 @@
if (/^(?:[/\\]|[A-Za-z]:)/.test(path)) return XREF_PATH_ABSOLUTE;
if (/[*?<>|:"]/.test(path)) return XREF_PATH_CHARS;
if (/\.dxf$/i.test(path)) return XREF_PATH_DXF;
if (/\.$/.test(path) && !/\.dwg\.$/i.test(path)) return XREF_PATH_DOT;

Check warning on line 1274 in src/rules.ts

View workflow job for this annotation

GitHub Actions / Verify (Node 22)

unicorn(prefer-string-starts-ends-with)

src/rules.ts:1274:7: Prefer String#endsWith over a regex with a dollar sign.

Check warning on line 1274 in src/rules.ts

View workflow job for this annotation

GitHub Actions / Verify (Node 24)

unicorn(prefer-string-starts-ends-with)

src/rules.ts:1274:7: Prefer String#endsWith over a regex with a dollar sign.
if (path.length > 32000) return XREF_PATH_LENGTH;
if (/\\[Mm]\+[1-5][0-9A-Fa-f]{4}/.test(path)) return XREF_PATH_MULTIBYTE;
return textProblem(path);
Expand Down
Loading
Loading