summaryrefslogtreecommitdiff
path: root/Userland/Libraries/LibPDF/Renderer.cpp
AgeCommit message (Collapse)Author
2023-03-25LibPDF: Scale vector paths with the viewJulian Offenhäuser
This ensures that lines have the correct size at every scale factor.
2023-03-25LibPDF: Accept floats as line dash pattern phasesJulian Offenhäuser
2023-03-25LibPDF: Allow pages with no specified contentsJulian Offenhäuser
The contents object may be omitted as per spec, which will just leave the page blank.
2023-03-06Everywhere: Stop using NonnullRefPtrVectorAndreas Kling
This class had slightly confusing semantics and the added weirdness doesn't seem worth it just so we can say "." instead of "->" when iterating over a vector of NNRPs. This patch replaces NonnullRefPtrVector<T> with Vector<NNRP<T>>.
2023-03-02LibPDF: Don't crash when a font hasn't been loaded yetRodrigo Tobar
This could happen because there was a problem while loading the first font in the document.
2023-03-02LibPDF: Prevent crashes when loading XObject streamsRodrigo Tobar
These streams might need a Filter that isn't implemented yet, and thus cannot be blindly MUST()-ed.
2023-02-24LibPDF: Refactor *Font classesRodrigo Tobar
The PDFFont class hierarchy was very simple (a top-level PDFFont class, followed by all the children classes that derived directly from it). While this design was good enough for some things, it didn't correctly model the actual organization of font types: * PDF fonts are first divided between "simple" and "composite" fonts. The latter is the Type0 font, while the rest are all simple. * PDF fonts yield a glyph per "character code". Simple fonts char codes are always 1 byte long, while Type0 char codes are of variable size. To this effect, this commit changes the hierarchy of Font classes, introducing a new SimpleFont class, deriving from PDFFont, and acting as the parent of Type1Font and TrueTypeFont, while Type0 still derives from PDFFont directly. This distinction allows us now to: * Model string rendering differently from simple and composite fonts: PDFFont now offers a generic draw_string method that takes a whole string to be rendered instead of a single char code. SimpleFont implements this as a loop over individual bytes of the string, with T1 and TT implementing draw_glyph for drawing a single char code. * Some common fields between T1 and TT fonts now live under SimpleFont instead of under PDFfont, where they previously resided. * Some other interfaces specific to SimpleFont have been cleaned up, with u16/u32 not appearing on these classes (or in PDFFont) anymore. * Type0Font's rendering still remains unimplemented. As part of this exercise I also took the chance to perform the following cleanups and restructurings: * Refactored the creation and initialisation of fonts. They are all centrally created at PDFFont::create, with a virtual "initialize" method that allows them to initialise their inner members in the correct order (parent first, child later) after creation. * Removed duplicated code. * Cleaned up some public interfaces: receive const refs, removed unnecessary ctro/dtors, etc. * Slightly changed how Type1 and TrueType fonts are implemented: if there's an embedded font that takes priority, otherwise we always look for a replacement. * This means we don't do anything special for the standard fonts. The only behavior previously associated to standard fonts was choosing an encoding, and even that was under questioning.
2023-02-24LibPDF: Allow show_text to return errorsRodrigo Tobar
Errors can (and do) occur when trying to render text, and so far we've silently ignored them, making us think that all is well when it isn't. Letting show_text return errors will allow us to inform the user about these errors instead of having to hiding them.
2023-02-04LibPDF: Fix clipping of painting operationsRodrigo Tobar
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-02LibPDF: Stop calculating code points for glyphsRodrigo Tobar
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-01-26LibGfx: Remove `try_` prefix from bitmap creation functionsTim Schumacher
Those don't have any non-try counterpart, so we might as well just omit it.
2023-01-09AK+Everywhere: Rename FlyString to DeprecatedFlyStringTimothy Flynn
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-05LibPDF: Use subpixel accurate text renderingMacDue
This just enables the new tricks from LibGfx with the same nice improvements :^)
2022-12-16LibPDF: Don't abort on unsupported drawing operationsRodrigo Tobar
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-16LibPDF: Switch to best-effort PDF renderingRodrigo Tobar
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-10LibPDF: Add initial image display supportRodrigo Tobar
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-10LibPDF: Refactor parsing of ColorSpacesRodrigo Tobar
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-10LibPDF: Return results directly and avoid unpacking+packingRodrigo Tobar
2022-12-06AK+Everywhere: Rename String to DeprecatedStringLinus Groh
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-11-30LibPDF: Add initial implementation of XObject renderingRodrigo Tobar
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-30LibPDF: Allow operators to receive optional resourcesRodrigo Tobar
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-30LibPDF: Render cubic bezier curvesRodrigo Tobar
The implementation of bezier curves already exists on Gfx, so implementing the PDF rendering of this command is trivial.
2022-11-30LibPDF: Communicate resources to ColorSpace, not PageRodrigo Tobar
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-26LibPDF: Fix path coordinates calculationRodrigo Tobar
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-25LibPDF: Introduce rendering preferences and show clipping pathsRodrigo Tobar
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-25LibPDF: Improve path clipping supportRodrigo Tobar
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-25LibPDF: Move all font handling to Type1Font and TrueTypeFont classesJulian Offenhäuser
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-25LibPDF: Convert dash pattern array elements to integers if necessaryJulian Offenhäuser
They may be floats instead.
2022-10-16LibPDF: Add very basic support for Adobe Type 1 font renderingJulian Offenhäuser
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-09-17LibPDF: Fix text positioning with operator TJJulian Offenhäuser
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-07-12Everywhere: Add sv suffix to strings relying on StringView(char const*)sin-ack
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-04-04PDFViewer: Support a continuous page view modeMatthew Olsson
2022-03-31LibPDF: Rename Command to OperatorMatthew Olsson
This is the correct name, according to the spec
2022-03-31LibPDF: Accept font size in PDFFont::get_char_widthMatthew Olsson
This will be required for TTF fonts
2022-03-31LibPDF: Move font files into their own directoryMatthew Olsson
2022-03-31LibPDF: Use Font /Widths array to derive character widthsMatthew Olsson
This makes the spacing between chars _much_ better!
2022-03-31LibPDF: Use AntiAliasingPainter in Renderer when possibleMatthew Olsson
2022-03-31LibPDF: Fix more bad Renderer text positioning calculationsMatthew Olsson
2022-03-31LibPDF: Handle SCN and scn operatorsMatthew Olsson
2022-03-31LibPDF: Move color space creation from Renderer to ColorSpaceMatthew Olsson
2022-03-29LibPDF: Require Document* in Parser constructorMatthew Olsson
This makes it a bit easier to avoid calling parser->set_document, an issue which cost me ~30 minutes to find.
2022-03-29LibPDF: Store a PDFFont in the Renderer's text stateMatthew Olsson
2022-03-07LibPDF: Fix "incorrect" matrix multiplication in RendererMatthew Olsson
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-07LibPDF: Implement marked renderer operations as nopsMatthew Olsson
2022-03-07LibPDF: Propagate errors in Renderer/PDFViewerMatthew Olsson
2022-03-07LibPDF: Propagate ColorSpace errorsMatthew Olsson
2022-03-07LibPDF: Propagate errors in Parser and DocumentMatthew Olsson
2021-09-20LibPDF: Replace Value class by AK::VariantBen Wiederhake
This decreases the memory consumption by LibPDF by 4 bytes per Value, compensating exactly for the increase in an earlier commit. :^)
2021-06-12LibPDF: Convert to east-const to comply with the recent style changesMatthew Olsson
2021-06-12LibPDF: Bake the flipped y-axis directly into the CTM matrixMatthew Olsson