Commit graph

54 commits

Author SHA1 Message Date
Rodrigo Tobar
82bac7e665 LibPDF: Fix clipping of painting operations
While the clipping logic was correct (current v/s new clipping path),
the clipping path contents weren't. This commit fixed that.

We calculate the clipping path in two places: when we set it to be the
whole page at graphics state creation time, and when we perform clipping
path intersection to calculate a new clipping path. The clipping path is
then used to limit painting by passing it to the painter (more
precisely, but passing its bounding box to the painter, as the latter
doesn't support arbitrary path clipping). For this last point the
clipping path must be in device coordinates.

There was however a mix of coordinate systems involved in the creation,
update and usage of the clipping path:

 * The initial values of the path (i.e., the whole page) were in user
   coordinates.
 * Clipping path intersection was performed against m_current_path,
   which is in device coordinates.
 * To perform the clipping operation, the current clipping path was
   assumed to be in user coordinates.

This mix resulted in the clipping not working correctly depending on the
zoom level at which one visualised a page.

This commit fixes the issue by always keeping track of the clipping path
in device coordinates. This means that the initial full-page contents
are now converted to device coordinates before putting them in the
graphics state, and that no mapping is performed when applied the
clipping to the painter.
2023-02-04 12:29:57 +01:00
Rodrigo Tobar
fb0c3a9e18 LibPDF: Stop calculating code points for glyphs
When rendering text, a sequence of bytes corresponds to a glyph, but not
necessarily to a character. This misunderstanding permeated through the
Encoding through to the Font classes, which were all trying to calculate
such values. Moreover, this was done only to identify "space"
characters/glyphs, which were getting a special treatment (e.g., avoid
rendering). Spaces are not special though -- there might be fonts that
render something for them -- and thus should not be skipped
2023-02-02 14:50:38 +01:00
Tim Schumacher
82a152b696 LibGfx: Remove try_ prefix from bitmap creation functions
Those don't have any non-try counterpart, so we might as well just omit
it.
2023-01-26 20:24:37 +00:00
Timothy Flynn
f3db548a3d AK+Everywhere: Rename FlyString to DeprecatedFlyString
DeprecatedFlyString relies heavily on DeprecatedString's StringImpl, so
let's rename it to A) match the name of DeprecatedString, B) write a new
FlyString class that is tied to String.
2023-01-09 23:00:24 +00:00
MacDue
91db49f7b3 LibPDF: Use subpixel accurate text rendering
This just enables the new tricks from LibGfx with the same nice
improvements :^)
2023-01-05 12:09:35 +01:00
Rodrigo Tobar
c4bc27f274 LibPDF: Don't abort on unsupported drawing operations
Instead of calling TODO(), which will abort the program, we now return
an Error specifying that we haven't implemented the drawing operation
yet. This will now nicely trickle up all the way through to the
PDFViewer, which will then notify its clients about the problem.
2022-12-16 10:04:23 +01:00
Rodrigo Tobar
e87fecf710 LibPDF: Switch to best-effort PDF rendering
The current rendering routine aborts as soon as an error is found during
rendering, which potentially severely limits the contents we show on
screen. Moreover, whenever an error happens the PDFViewer widget shows
an error dialog, and doesn't display the bitmap that has been painted so
far.

This commit improves the situation in both fronts, implementing
rendering now with a best-effort approach. Firstly, execution of
operations isn't halted after an operand results in an error, but
instead execution of all operations is always attempted, and all
collected errors are returned in bulk. Secondly, PDFViewer now always
displays the resulting bitmap, regardless of error being produced or
not. To communicate errors, an on_render_errors callback has been added
so clients can subscribe to these events and handle them as appropriate.
2022-12-16 10:04:23 +01:00
Rodrigo Tobar
adc45635e9 LibPDF: Add initial image display support
After adding support for XObject Form rendering, the next was to display
XObject images. This commit adds this initial support,

Images come in many shapes and forms: encodings: color spaces, bits per
component, width, height, etc. This initial support is constrained to
the color spaces we currently support, to images that use 8 bits per
component, to images that do *not* use the JPXDecode filter, and that
are not Masks. There are surely other constraints that aren't considered
in this initial support, so expect breakage here and there.

In addition to supporting images, we also support applying an alpha mask
(SMask) on them. Additionally, a new rendering preference allows to skip
image loading and rendering altogether, instead showing an empty
rectangle as a placeholder (useful for when actual images are not
supported). Since RenderingPreferences is becoming a bit more complex,
we add a hash option that will allow us to keep track of different
preferences (e.g., in a HashMap).
2022-12-10 10:49:03 +01:00
Rodrigo Tobar
ba16310739 LibPDF: Refactor parsing of ColorSpaces
ColorSpaces can be specified in two ways: with a stream as operands of
the color space operations (CS/cs), or as a separate PDF object, which
is then referred to by other means (e.g., from Image XObjects and other
entities). These two modes of addressing a ColorSpace are slightly
different and need to be addressed separately. However, the current
implementation embedded the full logic of the first case in the routine
that created ColorSpace objects.

This commit refactors the creation of ColorSpace to support both cases.
First, a new ColorSpaceFamily class encapsulates the static aspects of a
family, like its name or whether color space construction never requires
parameters. Then we define the supported ColorSpaceFamily objects.

On top of this also sit a breakage on how ColorSpaces are created. Two
methods are now offered: one only providing construction of no-argument
color spaces (and thus taking a simple name), and another taking an
ArrayObject, hence used to create ColorSpaces requiring arguments.

Finally, on top of *that* two ways to get a color space in the Renderer
are made available: the first creates a ColorSpace with a name and a
Resources dictionary, and another takes an Object. These model the two
addressing modes described above.
2022-12-10 10:49:03 +01:00
Rodrigo Tobar
287bb0feac LibPDF: Return results directly and avoid unpacking+packing 2022-12-10 10:49:03 +01:00
Linus Groh
6e19ab2bbc AK+Everywhere: Rename String to DeprecatedString
We have a new, improved string type coming up in AK (OOM aware, no null
state), and while it's going to use UTF-8, the name UTF8String is a
mouthful - so let's free up the String name by renaming the existing
class.
Making the old one have an annoying name will hopefully also help with
quick adoption :^)
2022-12-06 08:54:33 +01:00
Rodrigo Tobar
cb3e05f476 LibPDF: Add initial implementation of XObject rendering
This implementation currently handles Form XObjects only, skipping
image XObjects. When rendering an XObject, its resources are passed to
the underlying operations so they use those instead of the Page's.
2022-11-30 14:51:14 +01:00
Rodrigo Tobar
b3007c17bd LibPDF: Allow operators to receive optional resources
Operators usually assume that the resources its operations will require
will be the Page's. This assumption breaks however when XObjects with
their own resources come into the picture (and maybe other cases too).
In that case, the XObject's resources take precedence, but they should
also contain the Page's resources. Because of this, one can safely use
the XObject resources alone when given, and default to the Page's if
not.

This commit adds all operator calls an extra argument with optional
resources, which will be fed by XObjects as necessary.
2022-11-30 14:51:14 +01:00
Rodrigo Tobar
e58165ed7a LibPDF: Render cubic bezier curves
The implementation of bezier curves already exists on Gfx, so
implementing the PDF rendering of this command is trivial.
2022-11-30 14:51:14 +01:00
Rodrigo Tobar
fe5c823989 LibPDF: Communicate resources to ColorSpace, not Page
Resources can come from other sources (e.g., XObjects), and since the
only attribute we are reading from Page are its resources it makes sense
to receive resources instead. That way we'll be able to pass down
arbitrary resources that are not necessarily declared at the page level.
2022-11-30 14:51:14 +01:00
Rodrigo Tobar
d04613d252 LibPDF: Fix path coordinates calculation
Paths rendering was buggy because the map() function that translates
points from user space to bitmap space applied the vertical flip
conversion that the current transformation matrix already considers;
Hence, all paths were upside down. The only exception was the "re"
instruction, which manually adjusted the Y coordinate of its points to
be flipped again (and had a FIXME saying that this should be
unnecessary).

This commit fixes the map() function that maps userspace points to
bitmap coordinates. The "re" operator implementation has also been
simplified creating a rectangle first and mapping *that* instead of
mapping each point individually.
2022-11-26 08:56:35 +01:00
Rodrigo Tobar
e92ec26771 LibPDF: Introduce rendering preferences and show clipping paths
A new struct allows users to specify specific rendering preferences that
the Renderer class might use to paint some Document elements onto the
target bitmap. The first toggle allows rendering (or not) the clipping
paths on a page, which is useful for debugging.
2022-11-25 23:03:24 +01:00
Rodrigo Tobar
a1e36e8f78 LibPDF: Improve path clipping support
The existing path clipping support was broken, as it performed the
clipping operation as soon as the path clipping commands (W/W*) were
received. The correct behavior is to keep a clipping path in the
graphic state, *intersect* that with the current path upon receiving
W/W*, and apply the clipping when performing painting operations. On top
of that, the intersection happening at W/W* time does not affect the
painting operation happening on the current on-build path, but takes
effect only after the current path is cleared; therefore a current and a
next clipping path need to be kept track of.

Path clipping is not yet supported on the Painter class, nor is path
intersection. We thus continue using the same simplified bounding box
approach to calculate clipping paths.

Since now we are dealing with more rectangles-as-path code, I've made
helper functions to build a rectangle path and reuse it as needed.
2022-11-25 23:03:24 +01:00
Julian Offenhäuser
9cb3b23377 LibPDF: Move all font handling to Type1Font and TrueTypeFont classes
It was previously the job of the renderer to create fonts, load
replacements for the standard 14 fonts and to pass the font size back
to the PDFFont when asking for glyph widths.

Now, the renderer tells the font its size at creation, as it doesn't
change throughout the life of the font. The PDFFont itself is now
responsible to decide whether or not it needs to use a replacement
font, which still is Liberation Serif for now.

This means that we can now render embedded TrueType fonts as well :^)

It also makes the renderer's job much more simple and leads to a much
cleaner API design.
2022-11-25 22:44:47 +01:00
Julian Offenhäuser
8532ca1b57 LibPDF: Convert dash pattern array elements to integers if necessary
They may be floats instead.
2022-11-25 22:44:47 +01:00
Julian Offenhäuser
b14f0950a5 LibPDF: Add very basic support for Adobe Type 1 font rendering
Previously we would draw all text, no matter what font type, as
Liberation Serif, which results in things like ugly character spacing.

We now have partial support for drawing Type 1 glyphs, which are part of
a PostScript font program. We completely ignore hinting for now, which
results in ugly looking characters at low resolutions, but gain support
for a large number of typefaces, including most of the default fonts
used in TeX.
2022-10-16 17:44:54 +02:00
Julian Offenhäuser
97ed4106e5 LibPDF: Fix text positioning with operator TJ
As per spec, the positioning (or kerning) parameter of this operator
should translate the text matrix before the next showing of text.
Previously, this calculation was slightly wrong and also only applied
after the text was already shown.
2022-09-17 10:07:14 +01:00
sin-ack
3f3f45580a Everywhere: Add sv suffix to strings relying on StringView(char const*)
Each of these strings would previously rely on StringView's char const*
constructor overload, which would call __builtin_strlen on the string.
Since we now have operator ""sv, we can replace these with much simpler
versions. This opens the door to being able to remove
StringView(char const*).

No functional changes.
2022-07-12 23:11:35 +02:00
Matthew Olsson
3ecb41b7d9 PDFViewer: Support a continuous page view mode 2022-04-04 14:59:37 +02:00
Matthew Olsson
468ceb1b48 LibPDF: Rename Command to Operator
This is the correct name, according to the spec
2022-03-31 18:10:45 +02:00
Matthew Olsson
058cf5f7f7 LibPDF: Accept font size in PDFFont::get_char_width
This will be required for TTF fonts
2022-03-31 18:10:45 +02:00
Matthew Olsson
5f9d35909d LibPDF: Move font files into their own directory 2022-03-31 18:10:45 +02:00
Matthew Olsson
d2771eafc5 LibPDF: Use Font /Widths array to derive character widths
This makes the spacing between chars _much_ better!
2022-03-31 18:10:45 +02:00
Matthew Olsson
130846f337 LibPDF: Use AntiAliasingPainter in Renderer when possible 2022-03-31 18:10:45 +02:00
Matthew Olsson
8224ca6150 LibPDF: Fix more bad Renderer text positioning calculations 2022-03-31 18:10:45 +02:00
Matthew Olsson
34efc668d2 LibPDF: Handle SCN and scn operators 2022-03-31 18:10:45 +02:00
Matthew Olsson
1238e65d30 LibPDF: Move color space creation from Renderer to ColorSpace 2022-03-31 18:10:45 +02:00
Matthew Olsson
60c3e786be LibPDF: Require Document* in Parser constructor
This makes it a bit easier to avoid calling parser->set_document, an
issue which cost me ~30 minutes to find.
2022-03-29 02:52:57 +02:00
Matthew Olsson
9a4a3318a9 LibPDF: Store a PDFFont in the Renderer's text state 2022-03-29 02:52:57 +02:00
Matthew Olsson
4d509ff365 LibPDF: Fix "incorrect" matrix multiplication in Renderer
Incorrect is in quotes because the spec (both 1.7 and 2.0) specify this
multiplication as it was originally! However, flipping the order of
operations here makes the text in all of my test cases render in the
correct position.

The CTM is a transformation matrix between the text coordinate system
and the device coordinate system. However, being on the right-side of
the multiplication means that the CTM scale parameters don't have any
influence on the translation component of the left-side matrix. This
oddity is what originally led to me just trying this change to see if
it worked.
2022-03-07 10:53:57 +01:00
Matthew Olsson
6f1cfcf217 LibPDF: Implement marked renderer operations as nops 2022-03-07 10:53:57 +01:00
Matthew Olsson
b240d23a87 LibPDF: Propagate errors in Renderer/PDFViewer 2022-03-07 10:53:57 +01:00
Matthew Olsson
d82bd885ce LibPDF: Propagate ColorSpace errors 2022-03-07 10:53:57 +01:00
Matthew Olsson
73cf8205b4 LibPDF: Propagate errors in Parser and Document 2022-03-07 10:53:57 +01:00
Ben Wiederhake
f84a7e2e22 LibPDF: Replace Value class by AK::Variant
This decreases the memory consumption by LibPDF by 4 bytes per Value,
compensating exactly for the increase in an earlier commit. :^)
2021-09-20 17:39:36 +04:30
Matthew Olsson
612b183703 LibPDF: Convert to east-const to comply with the recent style changes 2021-06-12 22:45:01 +04:30
Matthew Olsson
0a4d8ef98d LibPDF: Bake the flipped y-axis directly into the CTM matrix 2021-06-12 22:45:01 +04:30
Matthew Olsson
449ef14895 LibPDF: Avoid calculating rendering matrix for every glyph 2021-06-12 22:45:01 +04:30
Matthew Olsson
c142dadbe8 LibPDF: Handle the TJ graphical operator 2021-06-12 22:45:01 +04:30
Matthew Olsson
47531619e3 LibPDF: Handle the gs graphical operator 2021-06-12 22:45:01 +04:30
Matthew Olsson
006f5498de LibPDF: Add support for the CalRGB ColorSpace
This isn't tested all that well, as the PDF I am testing with only uses
it for black (which is trivial). It can be tested further when LibPDF
is able to process more complex PDFs that actually use this color space
non-trivially.
2021-06-12 22:45:01 +04:30
Matthew Olsson
7b4e36bf88 LibPDF: Split ColorSpace into a different class for each color space
While unnecessary at the moment, this will allow for more fine-grained
control when complex color spaces get added.
2021-06-12 22:45:01 +04:30
Matthew Olsson
cafd7c11b4 LibPDF: Account for inverted y axis when rendering text 2021-06-12 22:45:01 +04:30
Andreas Kling
12a42edd13 Everywhere: codepoint => code point 2021-06-01 10:01:11 +02:00
Matthew Olsson
78f3bad7e6 LibPDF: Pre-initialize common FlyStrings in CommonNames.h 2021-05-25 00:24:09 +04:30