Log of #mupdf at irc.freenode.net.

Search:
 <<<Back 1 day (to 2018/03/20)20180321 
Tamir_Evan vtorri: Building mupdf-gl (which uses freeglut) for Windows targets isn't currently supported in Makefile and Makethird. How far do you get, if you add 'HAVE_GLUT=no' when you call 'make'?03:48.27 
vtorri Tamir_Evan : i have mutools and mupdf binaries, as well as the static libraries06:23.06 
  diff : http://codepad.org/buTYO8gJ06:26.09 
malc_ tor8: for the logs https://boblycat.org/~malc/mupdf-html-issue.html mupdf doesn't render all that it ought to09:13.58 
tor8 malc_: the xml in test.html is not well formed. the <meta> tag is never closed and thus swallows up the rest of the document.09:53.50 
  sebras: velix: mutool 'p' lists the object numbers for each page object, so you can save the time of hunting through the Root/Pages/Kids arrays09:57.05 
  sebras: and mutool with no extra argument lists the trailer by default, so no need for the 't' unless you mix it with other objects to show09:57.37 
  vtorri: the freeglut rules in Makethird only work for linux. I have not tried building it with MinGW; but it is probably possible if you add a windows specific section for freeglut in makethird09:59.43 
malc_ tor8: thanks, will fix10:02.16 
vtorri tor8 diff tobuild with msys2+migw-w64 : http://codepad.org/buTYO8gJ10:02.56 
  without glut for now10:03.13 
malc_ tor8: erm... meta tag is closed10:03.37 
tor8 malc_: don't trust firefox's "view source" -- it shows the source *after* it has fixed problems with it10:04.32 
malc_ tor8: i don't... i trust less10:04.46 
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>10:04.59 
tor8 malc_: huh, it was not closed when I downloaded it the first time!10:05.31 
malc_ i can assure you it was :)10:05.45 
  don't trust whatever is that you use to view text10:05.57 
  it opens meta tags for you10:06.04 
tor8 don't trust vim? that would be....problematic :)10:06.50 
malc_ install emacs, use vi-mode :)10:07.09 
  problem solved10:07.12 
tor8 this is ... strange.10:07.41 
malc_ you will also get an editor with actual unicode (complex shaping and such like) support for free10:07.43 
tor8 https://ghostscript.com/~tor/malc_file_1.txt and https://ghostscript.com/~tor/malc_file_2.txt10:08.52 
  how did I end up with the first one? this is making me doubt my sanity...10:09.07 
  unless you edited it while I was downloading10:09.15 
malc_ i haven't10:09.20 
  honest10:09.23 
tor8 ah, I know!10:09.46 
malc_ it's trimmed output of: http://repo.or.cz/llpp.git/blob/93b26d301f2a5583274cf2c5cd2df7c15ee836b9:/misc/llppac10:10.14 
  and you can check for yourself meta was always closed10:10.23 
  tor8: tell me10:10.38 
tor8 no, that wasn't it... I still have no idea.10:10.48 
  yeah, that's ... annoying. firefox saves a different source file than what I would get with 'wget'10:11.32 
  so that's one mystery solved10:11.48 
malc_ #!/bin/sh -e10:12.07 
  10:12.07 
  test -z "$1" && arg="$(xclip -o)" || arg="$1"10:12.08 
  #exec wget -c "$arg"10:12.08 
  10:12.11 
  # find a way to unescape output file name10:12.14 
  exec curl -O "$arg" -L -w "%{filename_effective} %{size_download}\n"10:12.17 
  10:12.19 
  i use that to download stuff...10:12.22 
  saner.. predictabler10:12.29 
tor8 now, what was the error with your file?10:12.43 
malc_ the lines after </br> [Unifont..] are not shown10:13.24 
tor8 the missing "unifont Medium 0 ..." line?10:13.24 
malc_ yep10:13.27 
tor8 yeah. you close the <pre> tag and then close a non-existing </br> tag which our parser interprets as closing the <html> tag10:13.59 
malc_ it should have been <br/>!10:14.16 
tor8 and you have a closing </body> tag but no opening body tag10:14.17 
malc_ tack som fan10:14.31 
tor8 if I add a <body> tag before the <pre> and close the <br/> tag properly, it works as expected10:14.38 
malc_ tor8: http://repo.or.cz/llpp.git/commitdiff/f9600b55f40e40bf5c1b63c32e79f1875524783510:17.15 
tor8 don't forget the opening <body> tag10:18.10 
  and I should think about integrating an HTML5 parser...10:18.36 
  but not now...10:18.48 
  vtorri: thanks. I'll make a commit for that.10:35.03 
vtorri tor8 i've manage somehow to *compile* build with freeglut but i have undef ref11:21.34 
  tor8 i can give you a diff but it would be just for you to have an idea of how you can do it11:22.03 
tor8 well, if you built it as the Makethird file now then you're building an X11/GLX version11:22.12 
  but maybe you modified the file list for windows?11:22.26 
vtorri i've modified the list for windws11:22.37 
  tor8 http://codepad.org/Yb4Dj8CR11:23.46 
tor8 vtorri: I was going to try it on my virtualbox install, but then MSYS2 doesn't support WinXP anymore so I can't11:24.29 
vtorri tor8 as you can see, there is a harcoded path in that patch (problem with my mingw-w64 installation) but you should get the idea11:24.34 
tor8 vtorri: you can add command line options by setting environment variables XLIBS and XCFLAGS11:25.39 
  if you add -L/opt/windows_64/... to XLIBS you shouldn't need that hardcoded path11:25.51 
  vtorri: what link errors remain?11:31.29 
vtorri build/release/platform/gl/gl-main.o:gl-main.c:(.text.startup.main+0x39e): undefined reference to `__imp_glutMainLoop'11:38.59 
  or11:39.00 
  a lot of them11:39.15 
tor8 could it be something to do with WINAPI stuff?11:46.24 
  or export def or dll crap11:46.36 
vtorri yes11:50.31 
sebras tor8: I know about 'p' and 't', but I felt that it was more informational for velix to see the chain of things.12:44.09 
tor8 sebras: cool. just wanted to point out the more useful tips :)12:50.58 
  sebras: there's a bunch of commits on tor/master for you to review whenever you get some time over13:00.44 
sebras fetches13:01.08 
  tor8: in "Load most annotations, even if they are missing appearances." I assume we used to filter out waay to many annotations.13:04.44 
HenryStiles join #ghostscript13:05.38 
tor8 sebras: we were randomly ignoring some annotations, yeah.13:05.48 
  not a lot, but if they were missing appearance streams we wouldn't even load them to create annotation streams ourselves13:06.07 
sebras ...which sounds silly.13:06.28 
tor8 now I filter them out based on type, so we ignore Link and Popup annotations only13:06.30 
sebras right.13:06.40 
  that seems reasonable. though what about annotations that we don't handle yet. like Movie..?13:06.57 
tor8 and thus we don't end up drawing Popup annotations that (erroneously) happen to have an AP13:07.00 
sebras right, that makes sense.13:08.30 
  adding .FORCE makes me happy.13:14.22 
  and "Auto-size HTML layout if layout page height is 0." I have looked at before too.13:14.48 
  tor8: with the WIN32 ifdefs, was it the case that for msys _WIN32 was defined by _MSC_VER was not?13:16.48 
  because that measn that the cahnge to include/mupdf/fitz/system.h is not described in the commit message.13:17.22 
  perhaps it is not the full solution to get it to compile though..?13:17.39 
tor8 sebras: yes. mingw defines _WIN32 but not MSC_VER13:18.51 
  MSC_VER stuff is VS specific only, so the change in system.h is to guard the windows specifics separately from msvc specifics13:19.16 
sebras I feel that makes it worth mentioning in the commit message, even if it might not warrant a separate commit.13:19.20 
tor8 sebras: I will amend the message.13:19.30 
sebras tor8: in that case LGTM. :)13:19.38 
  tor8: in "Use PDF object creation convenience functions." you also have the opportunity to turn pdf_dict_gets(ctx, dict, "BBox") and pdf_dict_gets(ctx, dict, "Matrix") in source/pdf/pdf-pattern.c into the corresponding pdf_dict_get() I think.13:23.44 
  and perhaps pdf_dict_gets(ctx, file_spec, "FS") in pdf-annot.c too.13:24.09 
  the other pdf_dict_*() that take strings appear to be paths, i.e. pdf_dict_getp()13:24.35 
  and if you feel like it git grep 'pdf_\(array\|dict\).*pdf_new' returns quite a list of similar locations.13:25.46 
  tor8: I don't like the ifdefs in "Fall back to PDF document handler if no handler is found." but I see why they are necessary. would it be beneficial to let the user of mupdf set a default document_handler?13:28.28 
tor8 sebras: the ones in pdf_annot-edit.c? yeah I could fix those too.13:28.33 
sebras tor8: as many as you can be bothered to change. :)13:29.02 
  tor8: I'll probably be irked enough to change the others eventually. :)13:29.18 
tor8 sebras: two more commits on tor/master then :)13:39.19 
sebras tor8: not yet pushed?13:40.41 
tor8 sorry, forgot the -f flag13:40.59 
  pushed now13:41.01 
sebras tor8: ok, how about allowing for the application to set a default document handler?13:42.46 
  that would probably remove the necessity of having the ifdefs in the document opening functions for PDF.13:43.09 
  in that case you could e.g. set the xps_document_handler as the default document handler if you decide to include xps but exclude pdf.13:44.18 
Tamir_Evan vtorri: To resolve your remaining errors, you may have to add gl-win32.o (and maybe gl-winres.o) to the rule for building mupdf-gl in the Makefile. This is how I did it in my fork of MuPDF: https://github.com/TamirEvan/mupdf/commit/019f3a09e7adb3b5c023b2067c3e43af8050b33d13:45.13 
vtorri Tamir_Evan then tor8 should look at this and even apply those changes :-)13:47.49 
sebras vtorri: it would of course be useful to get someone else verifying that the proposed fix works before commiting something that tor8 can't test easily.13:50.29 
vtorri sebras is it possible for you (mupdf devs) to check with wine ?13:51.17 
  sebras maybe it could be a solution13:51.31 
sebras vtorri: I have never built anything under wine, so I'd personally have an uphill struggle just to get things working I assume.13:52.12 
  vtorri: i.e. even compiling hello-world.c13:52.22 
vtorri compiling is not a problem if you have the mingw-w64 toolchain13:53.10 
  arch provides it and i guess other distro have it too13:53.34 
sebras vtorri: I don't, and making sure that mupdf compiles cleanly in msys/cygwin/whatever in a real windows environment is far more interesting. :)13:54.47 
  tor8: in rle_write() if the data to encode starts with 'XXX' we traverse the states ZERO -> ONE -> DIFF -> SAME right?14:08.54 
  tor8: what I don't get (yet) is why we need to skip the last two in the previous run..?14:09.26 
tor8 sebras: yes. I don't quite remember myself (I just revived ancient code)14:12.08 
sebras ok.14:12.17 
tor8 ah, yes14:12.19 
  because we flush the 'diff' run up to but not including the 2 bytes that were the same14:12.37 
  sebras: consider "ABCXXX" we want to emit "ABC" as a diff run, and start a new same run with X14:13.42 
  but we don't know that until we see the third X14:14.00 
  because ABCXX can be emitted as a diff run of length 514:14.15 
  but once you get more than two of the same, it's more compact to emit them as a same run14:14.30 
sebras ah, yes, because when we see the third X enc->run == 5, now I see.14:15.00 
tor8 ABCXX would be the same compressed length as a diff3(ABC) same2(X) or diff5(ABCXX)14:15.11 
vtorri Tamir_Evan : i have no gl-winres.o14:17.10 
tor8 vtorri: you need to create one using windres from gl-winres.rc14:18.19 
  same as the one created from platform/x11/win_res.rc14:18.56 
vtorri tor8 so it's in another patch from Tamir_Evan14:20.27 
sebras tor8: I think there might be a mistake in the naming of rle_flush_diff() and rle_flush_same(). they have been swapped, right?14:26.40 
  tor8: because rle_flush_diff() only writes a single byte while rle_flush_same() appears to write a sequence of bytes from enc->Buf14:27.03 
tor8 sebras: good catch!14:27.19 
Tamir_Evan vtorri: Sorry, that I had left over from when I added a commit to build mupdf-gl for MinGW with GLFW (which was used before they returned to using freeglut) (https://github.com/TamirEvan/mupdf/commit/98ba4be312588735e7ddc7c057cc38de606e9f75). See the top change to the Makefile there.14:30.40 
sebras do you aim to push an updated "Add fz_output encoding filters."?15:17.32 
  tor8: in fz_new_asciihex_output() and the others, if fz_new_output() fails it will call the drop-callback that frees state using fz_free() and then the fz_catch() in fz_new_asciihex_output() _also_ fz_free()s state. that's wrong.15:32.02 
tor8 sebras: oh. so it does. that simplifgies things.15:37.37 
  that also exposes the mistake in fz_new_ascii85_output where I set chain and return NULL :)15:38.27 
sebras tor8: ah, nice.15:39.18 
  tor8: in deflate_close() you call deflate(Z_FINISH) repeatedly if it returns Z_OK, that seems correct. but as I read zlib.h the same should be done for Z_BUF_ERROR, right..?15:40.21 
  tor8: not sure that this can ever happen in a normal situation, I'm just reading the docs here...15:40.50 
  tor8: oh and I'd appreciate a fz_warn() in defalte_drop() if deflateEnd() fails for whatever reason. similar to the one we have in close_flated().15:41.42 
  tor8: also why allocate fz_output with 8192 output buffer in fz_new_deflate_output() and then have a 32Kbyte output buffer in deflate_write(). wouldn't we want these to be the same?15:43.11 
tor8 errors in deflateEnd in deflate_drop are irrelevant (since we're throwing away the data, warning about discarded data from deflateEnd is a bit useless)15:52.53 
  the while loop for Z_FINISH *should* be correct. I checked extensively with the docs when writing it.15:54.23 
  the 8192 bytes buffer is the *input* buffer15:55.07 
  the 32k buffer is the *output* buffer15:55.16 
sebras deflateEnd() does check the state at the start (and may return Z_STREAM_ERROR) and checks the status at the end and may return Z_DATA_ERROR at that point.15:55.40 
  tor8: close.flated() also may not fail, but inflateEnd() does a similar state check which may result in Z_STREAM_ERROR.15:56.38 
  ah, yes, of course! I confused the two buffers, how silly of me.15:57.05 
tor8 IIRC those are sanity checks in case the API is called invalidly15:58.11 
sebras tor8: deflateStatecheck also checks deflate_state->status16:00.19 
  tor8: I'm not sure if deflate() may output data, return Z_OK and but leave ->status in a state in which it is not reasonable to call deflateEnd(). I'm guessing that's what may happen.16:01.07 
tor8 the state check is to ensure the nextAvail etc pointers are sane16:01.35 
sebras tor8: e.g. if ->state == BUSY_STATE then deflateEnd() returns Z_DATA_ERROR.16:01.37 
  ah, that BUSY_STATE happens when the stream is freed prematurely.16:02.15 
  tor8: the part about Z_BUF_ERROR I mentioned above is here: https://github.com/madler/zlib/blob/master/zlib.h#L32816:03.11 
  tor8: that seems to happen if the output buffer is not big enough. not sure if that can ever happen with 32Kbyte.16:03.33 
tor8 in the while loop, if we get err != Z_OK then why would we want to continue calling deflate with Z_FINISH?16:03.41 
  sebras: probably if it is 0 bytes :)16:03.54 
  I think it's robust enough to cope with small buffers16:04.03 
  if we get either Z_STREAM_END or an error, we want to stop and be done with the loop16:04.42 
sebras tor8: if Z_BUF_ERROR happens it will very visible throw, and we ought to get a bug report if it happens in practice.16:05.48 
tor8 sebras: yeah. I think that's what we want deflate_close to do as well16:06.17 
  (but not deflate_drop which should just silently discard whatever has been buffered)16:06.28 
sebras tor5 tor8 (for the logs): In "Add fz_output encoding filters." s/enc/state/ perhaps? like with all the states in the other outputs.17:32.47 
  tor5 tor8 (for the logs): in "html: Keep 'b' instead of 'h' in boxes." I think I get most of the restructuring, but there are strill a few lines that throw me: in layout_block() you write "if (child->b > child->y)" this comparison is confusing to me, as is "if (box->list_item && box->y == box->b)" and "if (box->y == box->b)" later on in the same function.17:42.31 
  all three seem to be concerned with comparin b and y after at least one (or all) children has been laid out. I think all is well, and it is just me that need an explanation.17:43.29 
  tor5 tor8 (for the logs): in "html: Build box model for tables." in layout_table() it might be that cell->b > row->b at which point row->b is updated, later this affects box->b too. I'm a little confused as to whether this means that row->y and/or box->y would need to be adjusted too..?17:54.41 
  I also read that thead/tbody/tfoot only affect styling, not the layout, so perhaps they are not so difficult to handle later. :)17:57.45 
  tor5 tor8 (for the logs): in "Add pkcs7 helper library to MinGW build of mupdf viewer." I think it is worth while to add it to mujstest as well as it also fails to compile due to missing PKCS7_LIB.17:59.37 
  oh, and why is PKCS718:00.48 
  _LIB not needed for mupdf-gl?18:01.06 
  tor5 tor8 (for the logs): the top commit on tor/master only has me worried concerning clang, but then again that didn't work before either. perhaps clang doesn't even work in mingw/msys/whatever.18:22.59 
  tor5 tor8 (for the logs): with the above comments the rest LGTM.18:23.16 
tor8 sebras: because mupdf-gl doesn't validate signatures18:46.02 
fredross-perry tor8, sebras - I'm looking at a bug report that has two cases of crashing at the memset inside fz_clear_pixmap_with_value. There's a comment to the effect 'This function is horrible'. Shoud we be using something else? There are two calls to fz_clear_pixmap_with_value inside mupdf_native.c.18:46.25 
  I have a sample file if that's helpful.18:47.15 
tor8 fredross-perry: can you reproduce it with mutool draw?18:47.37 
fredross-perry I can't repro it at all. But I'll try that and see what happens.18:48.05 
tor8 my first thought is that the pixmap has been created with external memory backing18:48.33 
  like in fz_new_pixmap_with_data18:48.58 
fredross-perry it's fz_new_pixmap_with_bbox_and_data18:50.47 
  look at newNativeAndroidDrawDevice18:51.12 
tor8 fredross-perry: same underlying function then18:51.24 
fredross-perry known issues there?18:52.04 
tor8 lockNativeDevice does some weird trickery to set/unset the pixmap->samples pointer to the underlying android bitmap memory18:52.22 
sebras fredross-perry: the comment presumably is because of the cmyk handling I suspect.18:52.25 
fredross-perry Is there something I can tell you about the file itself that will help understand?18:52.50 
sebras tor8 (re mupdf-gl): yet. :)18:52.54 
tor8 fredross-perry: all I can say is, I doubt the bug is in fz_clear_pixmap_with_value18:53.57 
  somewhere somehow someone is fiddling with the pix->samples pointer and that pointer doesn't point to writable memory18:54.13 
  fredross-perry: the fz_pixmap that the android draw device creates are magic hackery that NEED to be locked and unlocked by bracketing anything that touches the pixmap with androidDrawDevice_lock and _unlock18:55.15 
sebras tor8: fredross-perry: could also be that the pixmap width/height/stride/components fields have been fiddled with (may cause buffer overwrite of pix->samples)18:55.45 
tor8 the bug could be in androidDrawDevice_lock18:56.04 
  but that's something you need to bug Robin_Watts about...18:56.20 
fredross-perry I notice that fz_new_draw_device is called outside th lock/unlock.18:57.08 
tor8 I don't think the fz_new_draw_device actually touches the pixmap18:57.56 
  but any device calls on the device need to be lock/unlock wrapped18:58.15 
sebras tor8: it doesn't.18:58.21 
fredross-perry ok18:58.29 
  I shall bug Robin.19:00.27 
tor8 sebras: if (child->b > child->y) just tests whether the child had any visible content19:01.10 
  it's all to do with how and when vertical margins get added or merged19:01.43 
sebras right, then I understand that part.19:02.04 
tor8 the table row layout is probably buggy :)19:02.16 
sebras that means that if (box->y == box->b) also tests if the box has any layout.19:02.25 
  ehm.. content.19:02.29 
tor8 yeah.19:02.56 
sebras tor8: I know, and these were the things I thought of when reading the code. row->y and box->y, but I was unsure.19:03.02 
  ->y ought to point to the top of the content, right?19:03.31 
tor8 setting row->b to the max of all cell->b is to adjust the row to be as tall as the tallest cell19:03.34 
  ->y is the top of the box, and ->b is the bottom of the box19:03.47 
sebras while ->b points to the bottom of the content (and below that there is margin/padding/wwhatever)19:03.51 
tor8 it was easier than dealing with box->y + box->h everywhere19:04.13 
sebras yes, that's what I got from the b vs h commit. it looked easier19:04.31 
tor8 yes, the y and b are the 'content' box (excluding the margins, but including padding)19:04.54 
  oh, or maybe it is excluding both margins and padding. it's been a while and I'm a bit fuzzy on the details.19:05.40 
  it looks like the x,y,w,b define the content area, excluding all margins, borders, and padding19:06.11 
sebras tor8: right, that's what I thought, ok, in that case row->y and box->y shouldn't be updated. but row->b needs to accomodate the biggest cell of the row, and box->b once all the rols have been handled. it all makes sense to me now. :)19:10.12 
  tor8: fredross-perry: if AndroidBitmap_lockPixels() were to fail with ANDROID_BITMAP_RESULT_ALLOCATION_FAILED in androidDrawDevice_lock() a RuntimeException is thrown, but the function just returns to lockNativeDevice() which simply proceeds with unlocked pixels and a pixmap->samples value that points to the dummy stack variable in newNativeAndroidDrawDevice() or is a stale pointer value from the previous19:22.47 
  execution.19:22.53 
  this is a case that we don't handle.19:22.53 
  is this what happens? I don't know.19:23.06 
fredross-perry not sure.19:23.16 
  Also I am spotting that fz_new_pixmap_with_bbox_and_data calculates a stride for the pixmap, which is then overridden by the next line of code. Does that make sense?19:23.54 
sebras overridden?19:24.27 
fredross-perry like recalculated with a larger width.19:24.50 
  fz_new_pixmap_with_bbox_and_data calcs a stride based on the bbox width, but the newNativeAndroidDrawDevice resets it using a passed-in larger value.19:25.45 
  but it seems to be necessary (I tried removing it)19:27.26 
sebras fredross-perry: I believe that is correct as that new width is the actual width in the AndroidBitmap as obtained from AndroidBitmap_getInfo().19:27.56 
fredross-perry ok19:28.07 
sebras fredross-perry: I'm unsure of whether this means that the full width of the bitmap will be redrawn everytime. perhaps.19:31.00 
fredross-perry I'm unsure of that as well.19:31.18 
sebras even though patchXY01 to newNativeAndroidDrawDevice() ask for something smaller.19:31.18 
  fredross-perry: I think I get it now. in androidDrawDevice_lock() xOffset and yOffset are taken into account to point pixmap->samples to the upper left corner of the patch to be drawn, but the stride of the full bitmap may be wider than the desired patch, so to go to the next line in the samples you need to increment by the full bitmap width, not the patch's width.19:34.16 
  width/stride, same same. :)19:34.32 
fredross-perry ok that makes sense.19:35.03 
sebras still there is nothing that handles the exception thrown in androidDrawDevice_lock().19:35.04 
fredross-perry right.19:35.13 
sebras not sure if that is what is happening, but I did see someone on SO that got the allocation failed error randomly (not resolution).19:35.39 
fredross-perry who, and when?19:36.05 
sebras fredross-perry: https://stackoverflow.com/questions/35671612/androidbitmap-lockpixels-fails-with-android-bitmap-result-allocation-failed19:36.42 
  fredross-perry: https://github.com/kikoso/android-stackblur/issues/2119:36.50 
  fredross-perry: but start by verifying that this is indeed what happens.19:37.01 
  it is just speculation on my part, but it still fits with you reported.19:37.27 
  the locking function should probably return some value and if we notice that the locking function indicates an error, we just ignore the drawing operation and throw the exception hoping that someone might catch it.19:38.27 
fredross-perry i love a good speculative fix.19:39.15 
sebras fredross-perry: don't. reproduce it first. :)19:39.49 
sebras needs to sleep.19:39.53 
fredross-perry one more: do jni_throw messages get logged in release mode?19:40.08 
vtorri tor8 do you know if there is a difference of rendering between poppler and mupdf ?20:05.38 
  with mupdf, it seems that the document is smoother than poppler, sharper20:06.24 
  is mupdf doing by default anti aliasing while poppler does not ?20:06.43 
tor8 vtorri: poppler and mupdf do not share rendering code20:22.10 
  mupdf does anti-aliasing and fractional character spacing20:22.30 
  poppler applies heavy font hinting and snaps character positioning to integers20:22.43 
 Forward 1 day (to 2018/03/22)>>> 
ghostscript.com #ghostscript
Search: