diff options
Diffstat (limited to 'tex/context/base/mkiv/lpdf-grp.lua')
-rw-r--r-- | tex/context/base/mkiv/lpdf-grp.lua | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/tex/context/base/mkiv/lpdf-grp.lua b/tex/context/base/mkiv/lpdf-grp.lua new file mode 100644 index 000000000..0eac52dfb --- /dev/null +++ b/tex/context/base/mkiv/lpdf-grp.lua @@ -0,0 +1,295 @@ +if not modules then modules = { } end modules ['lpdf-grp'] = { + version = 1.001, + comment = "companion to lpdf-ini.mkiv", + author = "Hans Hagen, PRAGMA-ADE, Hasselt NL", + copyright = "PRAGMA ADE / ConTeXt Development Team", + license = "see context related readme files" +} + +local type = type +local formatters, gsub = string.formatters, string.gsub +local concat = table.concat +local round = math.round + +local backends, lpdf = backends, lpdf + +local nodeinjections = backends.pdf.nodeinjections + +local colors = attributes.colors +local basepoints = number.dimenfactors["bp"] +local inches = number.dimenfactors["in"] + +local nodeinjections = backends.pdf.nodeinjections +local codeinjections = backends.pdf.codeinjections +local registrations = backends.pdf.registrations + +local pdfdictionary = lpdf.dictionary +local pdfarray = lpdf.array +local pdfconstant = lpdf.constant +local pdfboolean = lpdf.boolean +local pdfreference = lpdf.reference +local pdfflushobject = lpdf.flushobject + +-- can also be done indirectly: +-- +-- 12 : << /AntiAlias false /ColorSpace 8 0 R /Coords [ 0.0 0.0 1.0 0.0 ] /Domain [ 0.0 1.0 ] /Extend [ true true ] /Function 22 0 R /ShadingType 2 >> +-- 22 : << /Bounds [ ] /Domain [ 0.0 1.0 ] /Encode [ 0.0 1.0 ] /FunctionType 3 /Functions [ 31 0 R ] >> +-- 31 : << /C0 [ 1.0 0.0 ] /C1 [ 0.0 1.0 ] /Domain [ 0.0 1.0 ] /FunctionType 2 /N 1.0 >> + +local function shade(stype,name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps) + if steps then + color_a = color_a[1] + color_b = color_b[1] + end + local f = pdfdictionary { + FunctionType = 2, + Domain = pdfarray(domain), -- domain is actually a string + C0 = pdfarray(color_a), + C1 = pdfarray(color_b), + N = tonumber(n), + } + separation = separation and registrations.getspotcolorreference(separation) + local s = pdfdictionary { + ShadingType = stype, + ColorSpace = separation and pdfreference(separation) or pdfconstant(colorspace), + Function = pdfreference(pdfflushobject(f)), + Coords = pdfarray(coordinates), + Extend = pdfarray { true, true }, + AntiAlias = pdfboolean(true), + } + lpdf.adddocumentshade(name,pdfreference(pdfflushobject(s))) +end + +local function shade(stype,name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions) + local func = nil + if steps then + local list = pdfarray() + local bounds = pdfarray() + local encode = pdfarray() + for i=1,steps do + bounds[i] = fractions[i] or 1 + encode[2*i-1] = 0 + encode[2*i] = 1 + list [i] = pdfdictionary { + FunctionType = 2, + Domain = pdfarray(domain), -- domain is actually a string + C0 = pdfarray(color_a[i]), + C1 = pdfarray(color_b[i]), + N = tonumber(n), + } + end + func = pdfdictionary { + FunctionType = 3, + Bounds = bounds, + Encode = encode, + Functions = list, + Domain = pdfarray(domain), -- domain is actually a string + } + else + func = pdfdictionary { + FunctionType = 2, + Domain = pdfarray(domain), -- domain is actually a string + C0 = pdfarray(color_a), + C1 = pdfarray(color_b), + N = tonumber(n), + } + end + separation = separation and registrations.getspotcolorreference(separation) + local s = pdfdictionary { + ShadingType = stype, + ColorSpace = separation and pdfreference(separation) or pdfconstant(colorspace), + Function = pdfreference(pdfflushobject(func)), + Coords = pdfarray(coordinates), + Extend = pdfarray { true, true }, + AntiAlias = pdfboolean(true), + } + lpdf.adddocumentshade(name,pdfreference(pdfflushobject(s))) +end + +function lpdf.circularshade(name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions) + shade(3,name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions) +end + +function lpdf.linearshade(name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions) + shade(2,name,domain,color_a,color_b,n,colorspace,coordinates,separation,steps,fractions) +end + +-- inline bitmaps but xform'd +-- +-- we could derive the colorspace if we strip the data +-- and divide by x*y + +local template = "q BI %s ID %s > EI Q" +local factor = 72/300 + +function nodeinjections.injectbitmap(t) + -- encoding is ascii hex, no checking here + local xresolution, yresolution = t.xresolution or 0, t.yresolution or 0 + if xresolution == 0 or yresolution == 0 then + return -- fatal error + end + local colorspace = t.colorspace + if colorspace ~= "rgb" and colorspace ~= "cmyk" and colorspace ~= "gray" then + -- not that efficient but ok + local d = gsub(t.data,"[^0-9a-f]","") + local b = math.round(#d / (xresolution * yresolution)) + if b == 2 then + colorspace = "gray" + elseif b == 6 then + colorspace = "rgb" + elseif b == 8 then + colorspace = "cmyk" + end + end + colorspace = lpdf.colorspaceconstants[colorspace] + if not colorspace then + return -- fatal error + end + local d = pdfdictionary { + W = xresolution, + H = yresolution, + CS = colorspace, + BPC = 8, + F = pdfconstant("AHx"), + -- CS = nil, + -- BPC = 1, + -- IM = true, + } + -- for some reasons it only works well if we take a 1bp boundingbox + local urx, ury = 1/basepoints, 1/basepoints + -- urx = (xresolution/300)/basepoints + -- ury = (yresolution/300)/basepoints + local width, height = t.width or 0, t.height or 0 + if width == 0 and height == 0 then + width = factor * xresolution / basepoints + height = factor * yresolution / basepoints + elseif width == 0 then + width = height * xresolution / yresolution + elseif height == 0 then + height = width * yresolution / xresolution + end + local image = img.new { + stream = formatters[template](d(),t.data), + width = width, + height = height, + bbox = { 0, 0, urx, ury }, + } + return img.node(image) +end + +-- general graphic helpers + +function codeinjections.setfigurealternative(data,figure) + local request = data.request + local display = request.display + if display and display ~= "" then + local nested = figures.push { + name = display, + page = request.page, + size = request.size, + prefix = request.prefix, + cache = request.cache, + width = request.width, + height = request.height, + } + figures.identify() + local displayfigure = figures.check() + if displayfigure then + -- figure.aform = true + img.immediatewrite(figure) + local a = pdfarray { + pdfdictionary { + Image = pdfreference(figure.objnum), + DefaultForPrinting = true, + } + } + local d = pdfdictionary { + Alternates = pdfreference(pdfflushobject(a)), + } + displayfigure.attr = d() + figures.pop() + return displayfigure, nested + else + figures.pop() + end + end +end + +function codeinjections.getpreviewfigure(request) + local figure = figures.initialize(request) + if not figure then + return + end + figure = figures.identify(figure) + if not (figure and figure.status and figure.status.fullname) then + return + end + figure = figures.check(figure) + if not (figure and figure.status and figure.status.fullname) then + return + end + local image = figure.status.private + if image then + img.immediatewrite(image) + end + return figure +end + +function codeinjections.setfiguremask(data,figure) -- mark + local request = data.request + local mask = request.mask + if mask and mask ~= "" then + figures.push { + name = mask, + page = request.page, + size = request.size, + prefix = request.prefix, + cache = request.cache, + width = request.width, + height = request.height, + } + figures.identify() + local maskfigure = figures.check() + if maskfigure then + local image = maskfigure.status.private + if image then + img.immediatewrite(image) + local d = pdfdictionary { + Interpolate = false, + SMask = pdfreference(image.objnum), + } + figure.attr = d() + end + end + figures.pop() + end +end + +-- temp hack + +local factor = number.dimenfactors.bp + +function img.package(image) -- see lpdf-u3d ** + local boundingbox = image.bbox + local imagetag = "Im" .. image.index + local resources = pdfdictionary { + ProcSet = pdfarray { + pdfconstant("PDF"), + pdfconstant("ImageC") + }, + Resources = pdfdictionary { + XObject = pdfdictionary { + [imagetag] = pdfreference(image.objnum) + } + } + } + local width = boundingbox[3] + local height = boundingbox[4] + local xform = img.scan { + attr = resources(), + stream = formatters["%F 0 0 %F 0 0 cm /%s Do"](width,height,imagetag), + bbox = { 0, 0, width/factor, height/factor }, + } + img.immediatewrite(xform) + return xform +end |