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
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ broke. The heading is parsed by `scripts/release-notes.ps1`, so keep its shape;
under it is ordinary Markdown, and the renderer handles paragraphs, lists, links, `code`
and **bold**.

## 1.7.3 - 30 September 2026

### Microsoft Whiteboard imports closer to the original
Vertical and diagonal highlighter strokes now come out about as wide as they were,
instead of up to four times wider. Sticky notes and note grids have square corners.

### Lists and GIFs from Microsoft Whiteboard
Text, bulleted, and task lists now come across as text containers, with a box for each
task that shows whether it is done, and GIFs come across as pictures. They used to be
listed as left out.

## 1.7.2 - 30 September 2026

### Draw a rectangle with square corners
Expand Down
2 changes: 1 addition & 1 deletion Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
scripts/build-installer.ps1 both read it from here, so releasing is a reviewed change
to this line rather than an edit in a pipeline variable group.
-->
<VersionPrefix>1.7.2</VersionPrefix>
<VersionPrefix>1.7.3</VersionPrefix>
<LangVersion>latest</LangVersion>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ How the project is developed and shipped is documented separately:
- Whole-stroke erasing
- PNG, JPEG, BMP, GIF, and SVG import, clipboard bitmap paste, and Explorer drag-and-drop of images, text files, `.wimport` recipes, PowerPoint decks, and Microsoft Whiteboard exports
- PowerPoint decks imported as one picture per slide through PowerPoint from Microsoft 365: SVG, or PNG for a slide whose fonts are not installed, placed in one row per section, with an optional frame around each slide. **File → Open** creates a new board from the deck; **File → Import** and drag-and-drop add it below the board's content
- Boards exported from Microsoft Whiteboard as a `.zip` imported with their ink, pictures, shapes, sticky notes, text, connectors, links, and comments, and the pen's varying width kept. **File → Open** creates a new board from the export; **File → Import** and drag-and-drop add it below the board's content. [docs/microsoft-whiteboard-import.md](docs/microsoft-whiteboard-import.md) lists what is not carried over
- Boards exported from Microsoft Whiteboard as a `.zip` imported with their ink, pictures, shapes, sticky notes, text, lists, connectors, links, and comments, and the pen's varying width kept. **File → Open** creates a new board from the export; **File → Import** and drag-and-drop add it below the board's content. [docs/microsoft-whiteboard-import.md](docs/microsoft-whiteboard-import.md) lists what is not carried over
- SVG is stored as its markup and redrawn as vectors at every zoom and resize. Pasting SVG markup that was copied as text — the output of a DAX SVG measure, for instance — creates a picture, and copying an SVG container puts both the markup and a bitmap on the clipboard. Text set in a Microsoft 365 font such as Aptos is drawn in that font when Office has it on the machine
- Image selection, movement, resizing, and deletion
- Text containers created by pasting plain text, with display and in-place edit modes
Expand Down
63 changes: 47 additions & 16 deletions docs/microsoft-whiteboard-import.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Microsoft Whiteboard import

**Implemented in 1.7.0**, with the objects of older versions of the app in 1.7.1 and
1.7.2. This document records what a Microsoft Whiteboard export contains, how the
**Implemented in 1.7.0**, with the objects of older versions of the app in 1.7.1,
1.7.2, and 1.7.3. This document records what a Microsoft Whiteboard export contains, how the
importer maps it onto a board, and what it cannot carry over. Microsoft retires its
standalone Whiteboard apps on 16 October 2026 (see [retirement](retirement/README.md)),
and the export is the only way to take a board out of it. The format is undocumented.
Expand Down Expand Up @@ -54,13 +54,15 @@ no model of the board beyond what it draws.
| `InkGroup` | An SVG with a view box whose origin sits at the anchor, class `PenStroke`, `Highlighter`, or `Mixed`. One `g.inkStroke` per stroke with `transform="matrix(0.0078125, …)"`: 1/128 of a pixel. Inside it, a filled `path` outline and a `polyline.inkHitTestOverlay` centerline. |
| `FluidImage` | `div.imageComponent` with the size, and an `img` with a base64 data URI labelled `text/plain` whatever the picture is. |
| `AzureImage` | A picture on a board made with an older version of the app, written as a `FluidImage` is, with the data URI labelled `image/*`. |
| `AzureGif` | An animated GIF, written as an `AzureImage` is. Not seen in a sample; the web client converts it with the same function as `AzureImage`. |
| `DocumentPage` | A page of an inserted PDF, written as a `FluidImage` is. |
| `ReactionStickers` | A sticker, written as a 64 × 64 `FluidImage` with an SVG data URI. |
| `Shape` | An SVG whose `g` has `fill`, `stroke`, and `stroke-width` (in `pt`), and whose `path` draws the outline around the middle of the box. The shape's text sits in `div.textBoxContainer`. |
| `LegacyEllipse` | A shape from an older version of the app: an SVG `ellipse` with the outline in its `stroke` attribute and the width and fill in its style. The radii can differ from the SVG's box, in proportion as well as in size, and the page draws the radii. |
| `LegacyPolygon` | A shape from an older version of the app: an SVG `polygon` whose points start at the anchor, styled as a `LegacyEllipse` is. Every sample is a rectangle. |
| `Note` | A sticky note: `div.textBoxBackground` with a color class such as `softBlueGradient`, a 40-pixel author bar, and `div.stickyNote` with the text area's size and font size. |
| `GridList` | A note grid: a title editor, then `div.listChild` notes in a CSS grid of `repeat(n, auto)` columns. |
| `VerticalList`, `VerticalBulletList`, `VerticalCheckboxList`, `UnknownList` | A list of text, bullets, or tasks, in `div.legacyListContainer`: a title editor in `div.verticalListTitle`, a `div.listColumnHeading` with the column names, then one `div.listChild` per item with its icon, its text editor, who a task is assigned to (`div.assignedUserDisplayName`), and its likes. A done task's icon is `CheckmarkCircle` with the class `checkedListItemIcon`, an open one `StatusCircle` with `uncheckedListItemIcon`. The list is 44 + 284 + 76 pixels wide, or 44 + 364 + 76 when tasks have an Assigned to column. An `UnknownList` draws no items. Not seen in a sample; read from the web client's `ListContainerComponent`. |
| `PlainText` | A text box: `div.textbox.plainText` with `max-width` and `font-size`, inside a wrapper whose `justify-content` centers the text in a wider box when the text is centered. |
| `Connector` | An SVG with the route as a path from the anchor, and the head as a small path moved to one end with `translate`. |
| `Hyperlink` | A preview card with the page's picture, an `a` with the link and its title, and the description. |
Expand All @@ -73,9 +75,9 @@ no model of the board beyond what it draws.
centerline point with half the ink's width there as its radius. About 60% of the
strokes in the samples have one width; the rest vary by up to 3.3 times, because the
pen reported pressure.
- **Highlighter outline.** The tip is an axis-aligned rectangle twice as tall as it is
wide, drawn once at the start and swept along the centerline. Its height follows
pressure. The fill is the color at 0.4 alpha.
- **Highlighter outline.** The tip is an axis-aligned rectangle, twice as tall as it is
wide on most boards and nearly square on some, drawn once at the start and swept
along the centerline. Its height follows pressure. The fill is the color at 0.4 alpha.
- **Highlighter without a centerline.** Older versions of the app wrote some highlighter
strokes with an empty `polyline` and a scale other than 1/128. The outline is a square
tip followed by the sweep, as overlapping pieces, and the path cannot be recovered from
Expand Down Expand Up @@ -119,11 +121,12 @@ Windows client offers, from `paleYellowGradient` (#FEE15A) to `grayGradient` (#C
| Shape | `ShapeBoardObject` of the kind its outline has, with fill, outline, angle, and text |
| Older ellipse or polygon | `ShapeBoardObject`, an oval with the ellipse's radii or the kind the polygon's corners have, without text |
| Rectangle, in either form | `ShapeBoardObject`, `ShapeKind.Rectangle`, with square corners |
| Sticky note | `ShapeBoardObject`, rounded rectangle in the note's color, with the note's text |
| Note grid | A white rounded rectangle for the panel, a label for the title, and one note per cell |
| Sticky note | `ShapeBoardObject`, rectangle in the note's color, with the note's text |
| Note grid | A white rectangle for the panel, a label for the title, and one note per cell |
| Text box | `FreeTextBoardObject`, wrapped into the lines the box showed |
| Connector | `ConnectorBoardObject`, straight, with its ends bound to shapes they sit on |
| Link card | Markdown `TextBoardObject` titled *Link* |
| List | Markdown `TextBoardObject` titled *List*: the list's title in bold, then a Markdown list of bullets, or one line per item with ☒ for a done task and ☐ for an open one |
| Comment thread | Markdown `TextBoardObject` titled *Comment*, in a column to the right of the board |
| Anchor order | Z-order |
| Anything else | Counted and reported, not imported |
Expand Down Expand Up @@ -163,10 +166,19 @@ An earlier version measured the distance from each point to the nearest edge of
outline. That made small handwriting too thin, because the outline of a small loop
overlaps itself.

**Highlighter width.** A highlighter here has one width per stroke, a tip twice as wide
as tall, and a fixed opacity. Its thickness is half the upper quartile of the vertical
edges in the outline, so the height of a horizontal highlight matches the body of the
original stroke.
**Highlighter width.** A highlighter here has one width per stroke, a tip 4t wide and 2t
tall for a thickness t, and a fixed opacity. Microsoft's tip is measured from the
outline. Its width is what the tip adds to the centerline's width. Its height is the
mean of two measures that err in opposite directions: the upper quartile of the vertical
edges, which come mostly from the lightly pressed ends, and what the tip adds to the
centerline's height, which comes from the one point that reaches furthest. A band
across a run at any angle is as wide as the tip reaches across it, so t is the value
that makes the two bands agree best over the stroke's length, by least squares: half
the height for a horizontal stroke, a quarter of the width for a vertical one, and a
compromise for a scribble. Directions are taken over runs at least one tip long,
because a hand-drawn line is made of tiny steps and some of them are steep. Until 1.7.3
the thickness was half the quartile alone, which drew vertical highlights four times
too wide.

**Connectors** are bound at an end that lies within a few pixels of the edge of an
upright shape, as a fraction of its box. A turned shape is not bound, because its
Expand All @@ -182,11 +194,13 @@ parses in about 160 ms.
- **Pressure is approximated.** The export keeps the outline, not the pressure. The
recovered widths match the original closely at 150% zoom, but not exactly.
- **Highlighter shape.** The tip here is wider than tall, while Microsoft's is taller than
wide. A horizontal highlight has the same height and starts and ends a few pixels
further out. A vertical highlight comes out four times as wide as the original. A
highlight has one width throughout.
wide. A horizontal or a vertical highlight comes out about as wide as the original,
but a scribble that runs both ways gets one thickness between the two, and some of
its runs are wider or narrower than they were. A highlight has one width throughout,
and overlapping parts of one stroke do not darken as they do on the page.
- **Rainbow and Galaxy** are one color each.
- **Notes and note grids have rounded corners**, because they are rounded rectangles here.
- **Notes and note grids have square corners**, where Microsoft rounds them slightly.
Until 1.7.3 they were rounded rectangles, whose corners are much rounder.
- **An old highlighter scribble is a picture**, not ink, because its path is not in the
export. It moves and deletes as a picture, and it keeps the few small gaps the page
shows where the outline's pieces overlap.
Expand Down Expand Up @@ -214,8 +228,17 @@ parses in about 160 ms.
- PowerPoint pages, which the Windows client cannot insert, videos, and Loop components
- SVG pictures, which the Windows client refuses to insert
- Groups, which the Windows client does not offer
- GIFs and lists, which are read from the web client's code, not from a sample

Each would be reported by type if it arrives as an unknown object. Sticky notes cannot be
The web client's code names every type an export can hold. Its `data-whiteboard-type`
values, as of version 26.10910.101 in September 2026, are the types above and these,
which the importer reports and leaves out: `Table` (an ink-to-table grid from the
Windows 10 app), `LegacyTemplate`, `LegacySticker`, `LoopObject`,
`HostedFluidObject`, `GroupFluidObject`, `AppIframeHost`, `WorkItem`, `Frame`, and
`CustomElement`. The export replaces a Loop component and an app frame with a
placeholder picture.

Each is reported by type after the import. Sticky notes cannot be
rotated in the Windows client, with the mouse, the pen, or touch.

## Verification
Expand All @@ -234,3 +257,11 @@ classification, shape kinds and quarter turns, notes, grids, wrapping and center
connector binding, links, comments, turned pictures, Galaxy ink, placement, container
binding, the objects of older versions, and recognizing the ZIP, on three synthetic pages
built like an export.

For 1.7.3 every sample was compared tile by tile. A scratch tool imported each board
and drew it through `BoardRasterizer`, in tiles of 1600 × 1000 canvas pixels, and
headless Edge drew the same rectangles of the page by setting the canvas transform. A
blurred color difference flagged the tiles that disagree. Across the 18 teaching boards,
the pixels that differ fell from 1.33% of the ink to 0.41%, and the tiles scoring above
3% from ten to three, all highlighter scribbles. The test board differs by its
background and by the notes' corners and text, listed above.
6 changes: 3 additions & 3 deletions site/export-microsoft-whiteboard.html
Original file line number Diff line number Diff line change
Expand Up @@ -220,13 +220,13 @@ <h2 id="open">Open it in SQLBI Whiteboard</h2>
<h2 id="what-comes-across">What comes across</h2>
<ul>
<li>Ink at the same pen widths, and highlighter strokes.</li>
<li>Pictures, stickers, and the pages of inserted PDFs.</li>
<li>Pictures, GIFs, stickers, and the pages of inserted PDFs.</li>
<li>Shapes with their fill, outline, angle, and text.</li>
<li>Sticky notes and note grids, as shapes in the same colors with their text.</li>
<li>Text boxes, connectors, and links.</li>
<li>Text boxes, lists, connectors, and links.</li>
<li>Comments, as text beside the board with the names of their authors.</li>
</ul>
<p>A highlighter stroke has one width, and Rainbow and Galaxy ink become one color. Notes have rounded corners, and elbow connectors become straight. The background color and reactions are left out. After the import, a message lists anything the board did not bring across.</p>
<p>A highlighter stroke has one width, and Rainbow and Galaxy ink become one color. Elbow connectors become straight. The background color and reactions are left out. After the import, a message lists anything the board did not bring across.</p>
<p>SQLBI Whiteboard keeps each board in a file on your PC and has no real-time collaboration. <a href="compare.html">Compare</a> lists the differences from Microsoft Whiteboard.</p>
</article>

Expand Down
10 changes: 5 additions & 5 deletions site/guide.html
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ <h3>Bring a PowerPoint deck in</h3>

<section class="story" id="microsoft-whiteboard">
<h3>Bring a Microsoft Whiteboard board in</h3>
<p>A board exported from Microsoft Whiteboard as a ZIP comes across with its ink at the same pen widths, pictures, shapes, sticky notes, text, connectors, links, and comments. It can start a new board or join an existing one, below its content, and anything left out is listed after the import. <a href="export-microsoft-whiteboard.html">Export from Microsoft Whiteboard</a> shows how to make the ZIP.</p>
<p>A board exported from Microsoft Whiteboard as a ZIP comes across with its ink at the same pen widths, pictures, shapes, sticky notes, text, lists, connectors, links, and comments. It can start a new board or join an existing one, below its content, and anything left out is listed after the import. <a href="export-microsoft-whiteboard.html">Export from Microsoft Whiteboard</a> shows how to make the ZIP.</p>

<figure class="fig">
<div class="figbox">
Expand Down Expand Up @@ -695,19 +695,19 @@ <h3>Bring a Microsoft Whiteboard board in</h3>

<g transform="translate(350 40) scale(1.2)">
<g class="f15-1">
<rect x="15" y="46" width="54" height="50" rx="6" fill="#FEE15A"/>
<rect x="15" y="46" width="54" height="50" rx="2" fill="#FEE15A"/>
<rect x="24" y="64" width="34" height="4" rx="2" fill="#15171C" opacity=".45"/>
<rect x="28" y="73" width="26" height="4" rx="2" fill="#15171C" opacity=".45"/>
</g>
<g class="f15-2">
<rect x="77" y="46" width="54" height="50" rx="6" fill="#9FE1E7"/>
<rect x="77" y="46" width="54" height="50" rx="2" fill="#9FE1E7"/>
<rect x="89" y="64" width="30" height="4" rx="2" fill="#15171C" opacity=".45"/>
<rect x="85" y="73" width="38" height="4" rx="2" fill="#15171C" opacity=".45"/>
</g>
<g class="f15-3">
<path d="M104 97c0 28 6 40 20 40" fill="none" stroke="var(--fig-ink)" stroke-width="1.5"/>
<path d="M119 132l6 5-6 5" fill="none" stroke="var(--fig-ink)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<rect x="127" y="118" width="76" height="38" rx="7" fill="var(--fig-surface-2)" stroke="var(--fig-ink)" stroke-width="1.5"/>
<rect x="127" y="118" width="76" height="38" rx="2" fill="var(--fig-surface-2)" stroke="var(--fig-ink)" stroke-width="1.5"/>
<text x="165" y="141" font-size="11.5" fill="var(--fig-ink)" text-anchor="middle">Sales</text>
</g>
<g class="f15-4">
Expand All @@ -726,7 +726,7 @@ <h3>Bring a Microsoft Whiteboard board in</h3>
</div>
<figcaption>
<p>The board keeps its layout, and the connector stays bound to its shape.</p>
<p>Sticky notes become rounded shapes in their colors, and comments move to a column on the right.</p>
<p>Sticky notes become shapes in their colors, and comments move to a column on the right.</p>
</figcaption>
</figure>
</section>
Expand Down
Loading
Loading