Skip to content

Commit 0d85365

Browse files
authored
Merge pull request #638 from embedpdf/fix/normalise-cloudy-border
Normalise `PdfAnnotationBorderStyle.CLOUDY` to `SOLID`
2 parents 3f061ba + 226e671 commit 0d85365

19 files changed

Lines changed: 4584 additions & 6658 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
---
2+
'@embedpdf/engines': patch
3+
---
4+
5+
Fix two bugs that caused polygon (and square/circle) annotations created via the `createAnnotation` API with `strokeStyle: PdfAnnotationBorderStyle.CLOUDY` to be saved as a half-built stub missing `/C`, `/IC`, `/CA`, `/F`, `/BE`, `/RD`, and `/AP`:
6+
7+
- Normalise `PdfAnnotationBorderStyle.CLOUDY` to `SOLID` inside `setBorderStyle` before calling PDFium's `EPDFAnnot_SetBorderStyle`. Cloudy is not a `/BS/S` value — it is conveyed via the separate `/BE` (border effect) dict, which `setBorderEffect` already writes. PDFium previously rejected the call and aborted the rest of `addPolyContent` / `addShapeContent`, so the cloudy effect, colors, opacity, flags, and appearance stream were never written.
8+
- Fix the rollback path in `createPageAnnotation` so failed content-add calls actually remove the partially-built annotation. The previous code called `FPDFPage_RemoveAnnot(pagePtr, annotationPtr)`, but PDFium's C signature is `FPDFPage_RemoveAnnot(FPDF_PAGE, int index)` — the annotation pointer was interpreted as an out-of-range index and silently no-op'd, leaving the stub annotation in the page. It now uses `removeAnnotationByName` (via `EPDFPage_RemoveAnnotByName`) and closes the annotation handle.
9+
10+
The `PdfAnnotationBorderStyle.CLOUDY` enum value is now treated as a deprecated alias for `SOLID + cloudyBorderIntensity` and is slated for removal in the next major release.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@embedpdf/pdfium': patch
3+
---
4+
5+
Fix callout FreeText annotations rendering with a black background when the fill color is transparent.
6+
7+
In `GenerateFreeTextAP`'s callout branch, the text-box rectangle was painted unconditionally with operator `B` (fill + stroke). When `/C` was absent, no fill colour was emitted, so `B` fell back to PDF's default black fill. Now the fill defaults to transparent via `GetColorStringWithDefault` and the paint operator is picked dynamically with `GetPaintOperatorString`, mirroring `GenerateCircleAP` / `GenerateSquareAP`.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@embedpdf/snippet': patch
3+
---
4+
5+
Re-export the annotation API surface from `@embedpdf/models` through the snippet bundle so consumers can use named enums and typed annotation shapes instead of hardcoding numeric subtype/border-style values.
6+
7+
Newly exported from `@embedpdf/snippet`:
8+
9+
- Enums: `PdfAnnotationBorderStyle`, `PdfAnnotationLineEnding`, `PdfAnnotationFlags`, `PdfAnnotationName`, `PdfAnnotationIcon`, `PdfAnnotationState`, `PdfAnnotationStateModel`, `PdfAnnotationReplyType`, `PdfAnnotationObjectStatus`, `PdfBlendMode`, `PdfStampFit`, `AppearanceMode`.
10+
- Annotation flag helpers: `PdfAnnotationFlagName`, `flagsToNames`, `namesToFlags`.
11+
- Annotation object types: `PdfAnnotationObjectBase`, `PdfAnnotationObject`, `PdfSupportedAnnoObject`, `PdfUnsupportedAnnoObject`, `PdfTextAnnoObject`, `PdfLinkAnnoObject`, `PdfFreeTextAnnoObject`, `PdfLineAnnoObject`, `PdfSquareAnnoObject`, `PdfCircleAnnoObject`, `PdfPolygonAnnoObject`, `PdfPolylineAnnoObject`, `PdfHighlightAnnoObject`, `PdfUnderlineAnnoObject`, `PdfSquigglyAnnoObject`, `PdfStrikeOutAnnoObject`, `PdfCaretAnnoObject`, `PdfInkAnnoObject`, `PdfInkListObject`, `PdfPopupAnnoObject`, `PdfFileAttachmentAnnoObject`, `PdfWidgetAnnoObject`, `PdfRedactAnnoObject`, `PdfRectDifferences`, `LinePoints`, `LineEndings`, `PdfAnnotationOf`.
12+
- Create-context types: `AnnotationCreateContext`, `AnnotationContextMap`.
13+
- Geometry / color: `Position`, `Size`, `Rect`, `WebColor`.
14+
15+
`PdfAnnotationSubtype` and `PdfStampAnnoObject` were already exported and continue to work unchanged.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
---
2+
'@embedpdf/snippet': patch
3+
---
4+
5+
Add Brazilian Portuguese (`pt-BR`) as a built-in locale of the snippet viewer.
6+
7+
- New `brazilianPortugueseTranslations` export from `@embedpdf/snippet`, covering the full translation schema so users see localised strings everywhere (search panel, password prompt, document-error dialog, outline, comments, blend-mode picker, link dialog, full protect/security flows, signature flow, etc.) — no English fallback noise.
8+
- Registered in the default `i18n.locales` array alongside the existing nine locales, so the viewer's language picker now lists "Português (Brasil)" out of the box.
9+
- The wide-label responsive override that used to be German/Dutch-only now also applies to `pt-BR`, because words like "Visualizar" (10) and "Formulário" (10) are as wide as German labels and would otherwise overflow the toolbar at the `md` breakpoint. The override group id was renamed from `germanic-languages` to `wide-label-languages` to reflect the broader scope; behaviour for `de`/`nl` is unchanged.

packages/engines/src/lib/pdfium/engine.ts

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,7 +1408,13 @@ export class PdfiumNative implements IPdfiumExecutor {
14081408
}
14091409

14101410
if (!isSucceed) {
1411-
this.pdfiumModule.FPDFPage_RemoveAnnot(pageCtx.pagePtr, annotationPtr);
1411+
// FPDFPage_RemoveAnnot's C signature is (FPDF_PAGE, int index), not
1412+
// (FPDF_PAGE, FPDF_ANNOTATION). Passing the annotation pointer here is
1413+
// interpreted as an out-of-range index and silently no-ops, leaving the
1414+
// half-built annotation in the page. Use the name-based remover instead,
1415+
// which matches how /NM was set above.
1416+
this.removeAnnotationByName(pageCtx.pagePtr, annotation.id);
1417+
this.pdfiumModule.FPDFPage_CloseAnnot(annotationPtr);
14121418
pageCtx.release();
14131419
this.logger.perf(
14141420
LOG_SOURCE,
@@ -6410,7 +6416,20 @@ export class PdfiumNative implements IPdfiumExecutor {
64106416
style: PdfAnnotationBorderStyle,
64116417
width: number,
64126418
): boolean {
6413-
return this.pdfiumModule.EPDFAnnot_SetBorderStyle(annotationPtr, style, width);
6419+
// PDFium's EPDFAnnot_SetBorderStyle (and the PDF spec) only accept the
6420+
// /BS /S names S/D/B/I/U. CLOUDY isn't a /BS/S value — it's conveyed via
6421+
// the separate /BE (border effect) dict, which setBorderEffect() writes
6422+
// later for polygon/square/circle. Normalise CLOUDY to SOLID here so a
6423+
// caller passing strokeStyle: CLOUDY (sponsor API convention) doesn't
6424+
// make PDFium reject the call and abort the rest of the save.
6425+
//
6426+
// TODO(next-major): remove the PdfAnnotationBorderStyle.CLOUDY enum value
6427+
// entirely. Cloudy is not a border-style; callers should use
6428+
// strokeStyle: SOLID + cloudyBorderIntensity: N. Once the enum value is
6429+
// gone, this normalisation can be deleted.
6430+
const effectiveStyle =
6431+
style === PdfAnnotationBorderStyle.CLOUDY ? PdfAnnotationBorderStyle.SOLID : style;
6432+
return this.pdfiumModule.EPDFAnnot_SetBorderStyle(annotationPtr, effectiveStyle, width);
64146433
}
64156434

64166435
/**

packages/pdfium/pdfium-src

Submodule pdfium-src updated 570 files

0 commit comments

Comments
 (0)