diff --git a/assets/webui/index.html b/assets/webui/index.html
index 89c18d0..77ee46d 100644
--- a/assets/webui/index.html
+++ b/assets/webui/index.html
@@ -33,6 +33,12 @@
+
diff --git a/assets/webui/ofdgo.css b/assets/webui/ofdgo.css
index 0da9bdc..9a3ee4f 100644
--- a/assets/webui/ofdgo.css
+++ b/assets/webui/ofdgo.css
@@ -217,6 +217,10 @@ button:not(:disabled):hover {
color: #1f2428;
}
+.dpi-select {
+ width: 54px;
+}
+
.format-select:focus,
.format-select:focus-visible {
border-color: var(--accent);
@@ -1078,6 +1082,10 @@ body[data-hide-meta] .meta-panel {
padding: 0 3px;
}
+ .dpi-select {
+ width: 48px;
+ }
+
.footer-links {
justify-content: flex-end;
}
diff --git a/assets/webui/ofdgo.js b/assets/webui/ofdgo.js
index 9e53382..89ee969 100644
--- a/assets/webui/ofdgo.js
+++ b/assets/webui/ofdgo.js
@@ -18,6 +18,7 @@ const COMMON_FONT_NAMES = [
];
const LOCAL_FONT_LOAD_LIMIT = 16;
const COMPACT_LAYOUT = window.matchMedia("(max-width: 900px)");
+const DEFAULT_RENDER_DPI = 300;
const STATUS = {
ready: "选择 OFD 文件",
opening: "正在打开 OFD",
@@ -59,6 +60,7 @@ const state = {
pageIndex: 0,
scale: 1,
fitMode: "width",
+ renderDPI: DEFAULT_RENDER_DPI,
renderAnnotations: true,
pageCache: new Map(),
pageInFlight: new Map(),
@@ -92,6 +94,7 @@ const el = {
fitButton: document.querySelector("#fitButton"),
fitHeightButton: document.querySelector("#fitHeightButton"),
annotationButton: document.querySelector("#annotationButton"),
+ renderDPI: document.querySelector("#renderDPI"),
pageExportFormat: document.querySelector("#pageExportFormat"),
exportPageButton: document.querySelector("#exportPageButton"),
exportButton: document.querySelector("#exportButton"),
@@ -136,6 +139,7 @@ el.zoomInButton.addEventListener("click", () => setScale(state.scale + 0.1));
el.fitButton.addEventListener("click", fitWidth);
el.fitHeightButton.addEventListener("click", fitHeight);
el.annotationButton.addEventListener("click", toggleAnnotations);
+el.renderDPI.addEventListener("change", changeDPI);
el.exportPageButton.addEventListener("click", exportCurrentPage);
el.exportButton.addEventListener("click", exportPDF);
el.pageInput.addEventListener("change", () => {
@@ -730,6 +734,19 @@ async function toggleAnnotations() {
});
}
+async function changeDPI() {
+ state.renderDPI = currentRenderDPI();
+ if (!state.ofdBytes || !state.doc) {
+ return;
+ }
+ await openDocument({
+ pageIndex: state.pageIndex,
+ fitMode: state.fitMode,
+ scale: state.scale,
+ skipAutoFonts: true,
+ });
+}
+
function removeFont(id) {
state.localFonts = state.localFonts.filter((font) => font.id !== id);
state.userFonts = state.userFonts.filter((font) => font.id !== id);
@@ -873,7 +890,7 @@ async function openDocument(options = {}) {
if (openSeq !== state.openSeq) {
return;
}
- const doc = callWASM("ofdgoOpen", state.ofdBytes, resetLocalFonts ? uploadedFonts() : allFonts(), state.renderAnnotations);
+ const doc = callWASM("ofdgoOpen", state.ofdBytes, resetLocalFonts ? uploadedFonts() : allFonts(), state.renderAnnotations, state.renderDPI);
if (openSeq !== state.openSeq) {
return;
}
@@ -881,7 +898,7 @@ async function openDocument(options = {}) {
const pageIndex = Math.min(Math.max(options.pageIndex || 0, 0), Math.max(pageCount - 1, 0));
state.doc = doc;
state.pageIndex = pageIndex;
- state.scale = 1;
+ state.scale = options.scale || 1;
state.fitMode = options.fitMode || "width";
if (!options.skipAutoFonts && await autoLoadDocumentLocalFonts(openSeq)) {
if (openSeq !== state.openSeq) {
@@ -2183,6 +2200,10 @@ function exportFormatInfo(value) {
return state.exportFormats.find((format) => format.value === value) || null;
}
+function currentRenderDPI() {
+ return Number.parseFloat(el.renderDPI.value) || DEFAULT_RENDER_DPI;
+}
+
function formatBytes(size, fallback = "PDF") {
if (!Number.isFinite(size) || size <= 0) {
return fallback;
diff --git a/internal/webui/wasm.go b/internal/webui/wasm.go
index 7e54337..ac733be 100644
--- a/internal/webui/wasm.go
+++ b/internal/webui/wasm.go
@@ -79,7 +79,7 @@ func safeCall(fn func([]js.Value) (any, error), args []js.Value) (data any, err
// 入参: args 浏览器参数
// 返回: any 文档信息, error 错误信息
func openDocument(args []js.Value) (any, error) {
- if len(args) < 3 {
+ if len(args) < 4 {
return nil, fmt.Errorf("missing open arguments")
}
data, err := bytesFromJS(args[0])
@@ -91,11 +91,12 @@ func openDocument(args []js.Value) (any, error) {
return nil, err
}
renderAnnotations := args[2].Bool()
+ dpi := args[3].Float()
if currentSession != nil {
_ = currentSession.Close()
currentSession = nil
}
- session, err := Open(data, OpenOptions{Fonts: fonts, RenderAnnotations: renderAnnotations})
+ session, err := Open(data, OpenOptions{Fonts: fonts, DPI: dpi, RenderAnnotations: renderAnnotations})
if err != nil {
return nil, err
}
diff --git a/internal/webui/webui.go b/internal/webui/webui.go
index 9919516..bed492c 100644
--- a/internal/webui/webui.go
+++ b/internal/webui/webui.go
@@ -30,6 +30,7 @@ import (
// OpenOptions 打开OFD文档选项
type OpenOptions struct {
Fonts []FontFile
+ DPI float64
RenderAnnotations bool
}
@@ -186,6 +187,9 @@ func Open(data []byte, opts OpenOptions) (*Session, error) {
return nil, err
}
var rendererOptions []ofdgo.RendererOption
+ if opts.DPI > 0 {
+ rendererOptions = append(rendererOptions, ofdgo.WithDPI(opts.DPI))
+ }
if len(opts.Fonts) > 0 {
fontFS := ofdgo.NewFontFS(opts.Fonts)
if fontFS.Len() == 0 {