in packages/maker.js/src/core/pdf.ts [11:113]
    export function toPDF(doc: PDFKit.PDFDocument, modelToExport: IModel, options?: IPDFRenderOptions) {
        if (!modelToExport) return;
        //fixup options
        var opts: IPDFRenderOptions = {
            fontName: 'Courier',
            fontSize: 9,
            origin: [0, 0],
            stroke: "#000",
        };
        extendObject(opts, options);
        //try to get the unit system from the itemToExport
        var scale = 1;
        var exportUnits = opts.units || modelToExport.units;
        if (exportUnits) {
            //convert to inch
            scale = units.conversionScale(exportUnits, unitType.Inch);
        } else {
            //assume pixels, convert to inch
            scale = 1 / 100;
        }
        //from inch to PDF PPI
        scale *= 72;
        //TODO scale each element without a whole clone
        var scaledModel = model.scale(cloneObject(modelToExport), scale);
        var size = measure.modelExtents(scaledModel);
        var left = -size.low[0];
        var offset: IPoint = [left, size.high[1]];
        offset = point.add(offset, opts.origin);
        model.findChains(
            scaledModel,
            function (chains: IChain[], loose: IWalkPath[], layer: string) {
                function single(walkedPath: IWalkPath) {
                    var pathData = pathToSVGPathData(walkedPath.pathContext, walkedPath.offset, offset);
                    doc.path(pathData).stroke(opts.stroke);
                }
                chains.map(function (chain: IChain) {
                    if (chain.links.length > 1) {
                        var pathData = chainToSVGPathData(chain, offset);
                        doc.path(pathData).stroke(opts.stroke);
                    } else {
                        var walkedPath = chain.links[0].walkedPath;
                        if (walkedPath.pathContext.type === pathType.Circle) {
                            var fixedPath: IPath;
                            path.moveTemporary([walkedPath.pathContext], [walkedPath.offset], function () {
                                fixedPath = path.mirror(walkedPath.pathContext, false, true);
                            });
                            path.moveRelative(fixedPath, offset);
                            //TODO use only chainToSVGPathData instead of circle, so that we can use fill
                            doc.circle(fixedPath.origin[0], fixedPath.origin[1], (<IPathCircle>walkedPath.pathContext).radius).stroke(opts.stroke);
                        } else {
                            single(walkedPath);
                        }
                    }
                });
                loose.map(single);
            },
            { byLayers: false }
        );
        doc.font(opts.fontName).fontSize(opts.fontSize);
        model.getAllCaptionsOffset(scaledModel).forEach(caption => {
            //measure the angle of the line, prior to mirroring
            const a = angle.ofLineInDegrees(caption.anchor);
            //mirror into pdf y coords
            const anchor = path.mirror(caption.anchor, false, true) as IPathLine;
            //move mirrored line by document offset
            path.moveRelative(anchor, offset);
            //measure center point of text
            const text = caption.text;
            const textCenter: IPoint = [doc.widthOfString(text) / 2, doc.heightOfString(text) / 2];
            //get center point on line
            const center = point.middle(anchor) as number[];
            const textOffset = point.subtract(center, textCenter);
            doc.rotate(-a, { origin: center });
            doc.text(text, textOffset[0], textOffset[1]);
            doc.rotate(a, { origin: center });
        });
    }