diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..6a790f3 --- /dev/null +++ b/Makefile @@ -0,0 +1,79 @@ +BIN = MacMuPDF + +TOOLCHAIN = /sdb/Retro68/Retro68-build/toolchain +ARCH = m68k-apple-macos + +CC = $(TOOLCHAIN)/bin/$(ARCH)-gcc +CXX = $(TOOLCHAIN)/bin/$(ARCH)-g++ +LD = $(TOOLCHAIN)/bin/$(ARCH)-ld +AS = $(TOOLCHAIN)/bin/$(ARCH)-as +AR = $(TOOLCHAIN)/bin/$(ARCH)-ar +REZ = $(TOOLCHAIN)/bin/Rez +MAKE_APPL = $(TOOLCHAIN)/bin/MakeAPPL +LAUNCH_APPL = $(TOOLCHAIN)/bin/LaunchAPPL + +CSRC = $(wildcard source/*.c source/**/*.c) +INC = $(wildcard source/*.h source/**/*.h) +OBJ = $(CSRC:.c=.o) +SHAREDIR = Shared +MUPDF_DIR = dep/mupdf-1.12.0-source +MUPDF_LIB_DIR = $(MUPDF_DIR)/build/release + +CFLAGS += -O2 -std=c11 -ffunction-sections +CFLAGS += -Wno-multichar -Wno-attributes #-Werror +CFLAGS += -I$(MUPDF_DIR)/include -I$(TOOLCHAIN)/$(ARCH)/include +LDFLAGS = -lretrocrt -lm -Wl,-gc-sections + +RINCLUDES = $(TOOLCHAIN)/RIncludes +REZFLAGS = -I$(RINCLUDES) + +MINI_VMAC_DIR=~/Mac/Emulation/Mini\ vMac +MINI_VMAC=$(MINI_VMAC_DIR)/Mini\ vMac +MINI_VMAC_LAUNCHER_DISK=$(MINI_VMAC_DIR)/launcher-sys.dsk + +all: $(BIN).dsk + +$(BIN).dsk: $(BIN).code.bin + $(REZ) $(RINCLUDES)/Retro68APPL.r -I$(RINCLUDES) --copy $(BIN).code.bin \ + -o $(BIN).bin --cc $(BIN).dsk --cc $(BIN).APPL --cc %$(BIN).ad \ + -t 'APPL' -c '????' + +$(BIN).code.bin: $(OBJ) $(MUPDF_LIB_DIR)/libmupdf.a $(MUPDF_LIB_DIR)/libmupdfthird.a + $(CC) -o $(BIN).code.bin $(OBJ) $(MUPDF_LIB_DIR)/libmupdf.a $(MUPDF_LIB_DIR)/libmupdfthird.a $(LDFLAGS) + +%.o: %.c + $(CC) $(CFLAGS) -o $@ -c $< + +$(MUPDF_LIB_DIR)/libmupdf.a: $(MUPDF_DIR)/generated + cd $(MUPDF_DIR) && make CC=$(CC) CXX=$(CXX) AR=$(AR) CROSSCOMPILE=yes XCFLAGS="-DNOCJK -DTOFU -DTOFU_CJK -DNO_CJK -DNOTO_SMALL -DFZ_PLOTTERS_RGB=1 -DFZ_PLOTTERS_G=1 -DFZ_PLOTTERS_CMYK=0 -DFZ_PLOTTERS_N=0 -DFZ_ENABLE_PDF=1 -DFZ_ENABLE_XPS=0 -DFZ_ENABLE_SVG=0 -DFZ_ENABLE_CBZ=0 -DFZ_ENABLE_IMG=0 -DFZ_ENABLE_TIFF=0 -DFZ_ENABLE_HTML=0 -DFZ_ENABLE_EPUB=0 -DFZ_ENABLE_JPX=1 -DFZ_ENABLE_JS=0 -DNO_ICC" libs + +$(MUPDF_LIB_DIR)/libmupdfthird.a: $(MUPDF_LIB_DIR)/libmupdf.a + +# This is run on the native platform before cross-compiling +$(MUPDF_DIR)/generated: $(MUPDF_DIR) + cd $< && make generate + +$(MUPDF_DIR): $(DEP_DIR) + curl https://mupdf.com/downloads/mupdf-1.12.0-source.tar.gz | tar xz + +$(DEP_DIR): + mkdir -p $@ + +MINI_VMAC_DIR=../vMac +MINI_VMAC=$(MINI_VMAC_DIR)/Mini\ vMac +MINI_VMAC_LAUNCHER_DISK=$(MINI_VMAC_DIR)/6.0.8.dsk + +MINI_VMAC_FLAGS=--emulator minivmac --minivmac-dir /sdb/Retro68/vMac --minivmac-path=/sdb/Retro68/vMac/Mini\ vMac --system-image /sdb/Retro68/vMac/6.0.8.dsk --autoquit-image /sdb/Retro68/vMac/autoquit-1.1.1_data.dsk + +run: $(BIN).dsk + $(MINI_VMAC) $(MINI_VMAC_LAUNCHER_DISK) $(BIN).dsk + #$(LAUNCH_APPL) $(MINI_VMAC_FLAGS) $(BIN).APPL + +clean: + rm -f $(BIN) $(BIN).dsk $(BIN).bin $(BIN).code.bin $(BIN).ad $(BIN).code.bin.gdb $(BIN).APPL "%$(BIN).ad" \ + $(MUPDF_LIB_DIR)/libmupdf.a $(MUPDF_LIB_DIR)/libmupdfthird.a \ + $(OBJ) $(CDEP) + rm -rf .finf .rsrc + + +.PHONY: clean run diff --git a/source/main.c b/source/main.c new file mode 100644 index 0000000..753bf67 --- /dev/null +++ b/source/main.c @@ -0,0 +1,54 @@ + +#include + +#include +#include +#include + +#include + +#include "render.h" +#include "utils.h" + +int main() +{ +#if !TARGET_API_MAC_CARBON + InitGraf(&qd.thePort); + InitFonts(); + InitWindows(); + InitMenus(); + TEInit(); + InitDialogs(NULL); + InitCursor(); +#endif + + Point where; + SFTypeList typeList; + SFReply reply; + char path_buf[MAX_PATHLEN]; + char* path; + + SetPt(&where, 100, 80); + SFGetFile(where, "\p", NULL, -1, typeList, NULL, &reply); + if (reply.good) + { + path = GetFullPath(path_buf, reply.vRefNum, reply.fName); + + WindowPtr doc_window; + doc_window = NewWindow(NULL, &(qd.screenBits.bounds), path, true, 0, (WindowPtr)-1, false, 0); + SetPort(doc_window); + + render(path, doc_window, 100, 0); + } + + EventRecord myEvent; + for (;;) + { + SystemTask(); + if (WaitNextEvent(everyEvent, &myEvent, 5L, NULL)) + if (myEvent.what == mouseDown) break; + } + + FlushEvents(everyEvent, -1); + return 0; +} diff --git a/source/render.c b/source/render.c new file mode 100644 index 0000000..cdcc1f1 --- /dev/null +++ b/source/render.c @@ -0,0 +1,102 @@ + +#include +#include + +#include +#include +#include + +#include + +#include "mupdf/fitz.h" +#include "render.h" + +int render(const char* filename, WindowPtr window, float zoom, int page_number) +{ + FILE *fp; + int page_count; + fz_context *ctx; + fz_document *doc; + fz_pixmap *pix; + fz_matrix ctm; + int x, y; + + /* Create a context to hold the exception stack and various caches. */ + ctx = fz_new_context(NULL, NULL, FZ_STORE_UNLIMITED); + if (!ctx) + { + DebugStr("\pfz_new_context failed"); + return EXIT_FAILURE; + } + + fz_set_aa_level(ctx, 0); + + /* Register the default file types to handle. */ + fz_try(ctx) + fz_register_document_handlers(ctx); + fz_catch(ctx) + { + //fprintf(stderr, "cannot register document handlers: %s\n", fz_caught_message(ctx)); + DebugStr("\pcannot register document handlers"); + fz_drop_context(ctx); + return EXIT_FAILURE; + } + + /* Open the document. */ + fz_try(ctx) + doc = fz_open_document(ctx, filename); + fz_catch(ctx) + { + DebugStr("\pcould not open document"); + fz_drop_context(ctx); + return EXIT_FAILURE; + } + + /* Count the number of pages. */ + fz_try(ctx) + page_count = fz_count_pages(ctx, doc); + fz_catch(ctx) + { + fprintf(stderr, "cannot count number of pages: %s\n", fz_caught_message(ctx)); + fz_drop_document(ctx, doc); + fz_drop_context(ctx); + return -1; + } + + if (page_number < 0 || page_number >= page_count) + { + fprintf(stderr, "page number out of range: %d (page count %d)\n", page_number + 1, page_count); + fz_drop_document(ctx, doc); + fz_drop_context(ctx); + return EXIT_FAILURE; + } + + /* Compute a transformation matrix for the zoom and rotation desired. */ + /* The default resolution without scaling is 72 dpi. */ + fz_scale(&ctm, zoom / 100, zoom / 100); + //fz_pre_rotate(&ctm, 0); + + /* Render page to an RGB pixmap. */ + fz_try(ctx) + pix = fz_new_pixmap_from_page_number(ctx, doc, page_number, &ctm, fz_device_gray(ctx), 0); + fz_catch(ctx) + { + fz_drop_document(ctx, doc); + fz_drop_context(ctx); + return EXIT_FAILURE; + } + + fz_bitmap *bitmap = fz_new_bitmap_from_pixmap(ctx, pix, fz_default_halftone(ctx, 1)); + + Rect bm_rect; + SetRect(&bm_rect, 0, 0, pix->w, pix->h); + BitMap qd_bitmap; + qd_bitmap.baseAddr = bitmap->samples; + qd_bitmap.rowBytes = bitmap->stride; + qd_bitmap.bounds = bm_rect; + + CopyBits(&qd_bitmap, &(window->portBits), &bm_rect, &bm_rect, srcCopy, NULL); + + return 0; + +} diff --git a/source/render.h b/source/render.h new file mode 100644 index 0000000..2d10625 --- /dev/null +++ b/source/render.h @@ -0,0 +1,5 @@ + +#include + +int render(const char* filename, WindowPtr window, float zoom, int page_number); + diff --git a/source/utils.c b/source/utils.c new file mode 100644 index 0000000..bb87302 --- /dev/null +++ b/source/utils.c @@ -0,0 +1,39 @@ + +#include + +#include +#include + +#include + +#include "utils.h" + +// from DGD + +const char* GetFullPath(char* buf, short vRefNum, const unsigned char* fname) +{ + Str255 str; + CInfoPBRec dir; + + buf += MAX_PATHLEN - 1; + buf[0] = '\0'; + memcpy(str, fname, fname[0] + 1); + + dir.dirInfo.ioNamePtr = str; + dir.dirInfo.ioCompletion = NULL; + dir.dirInfo.ioFDirIndex = 0; + dir.dirInfo.ioVRefNum = vRefNum; + dir.dirInfo.ioDrDirID = 0; + for (;;) + { + PBGetCatInfoSync(&dir); + memcpy(buf -= str[0], str + 1, str[0]); + if (dir.dirInfo.ioDrDirID == 2) + { + return buf; + } + *--buf = ':'; + dir.dirInfo.ioFDirIndex = -1; + dir.dirInfo.ioDrDirID = dir.dirInfo.ioDrParID; + } +} diff --git a/source/utils.h b/source/utils.h new file mode 100644 index 0000000..25840f4 --- /dev/null +++ b/source/utils.h @@ -0,0 +1,4 @@ + +#define MAX_PATHLEN 256 + +const char* GetFullPath(char* buf, short vRefNum, const unsigned char* fname);