mirror of
https://github.com/SerenityOS/serenity
synced 2024-09-06 17:06:31 +00:00
LibPDF+PDFViewer+MacPDF: Don't draw hidden text by default
Text can be rendered in various ways in PDFs: Filled, stroked, both filled and stroked, set as clipping path, hidden, or some combinations thereof. We don't implement any of this at the moment except "filled". Hidden text is used in scanned documents: The image of the scan is drawn in the background, and then OCRd text is "drawn" as hidden on top of the scanned bitmap. That way, the (hidden) text can be selected and copied, and it looks like you're selecting text from the scanned bitmap. Find-in-page also works similarly. (We currently have neither text selection nor find-in-page, but one day we will.) Now that we have pretty good support for CCITT and are growing some support for JBIG2, we now draw both the scanned background image as well as the foreground text. They're not always perfectly aligned. This change makes it so that we don't render text that's marked as hidden. (We still do most of the coordinate math, which will probably come in handy at some point when we implement text selection.) This makes these scanned documents appear as they're supposed to appear (at least in documents where we manage to decode the background bitmap). This also adds a debug option to force rendering of hidden text.
This commit is contained in:
parent
ead742886b
commit
21917e7b1e
|
@ -31,5 +31,6 @@
|
||||||
- (IBAction)toggleClipPaths:(id)sender;
|
- (IBAction)toggleClipPaths:(id)sender;
|
||||||
- (IBAction)toggleClipText:(id)sender;
|
- (IBAction)toggleClipText:(id)sender;
|
||||||
- (IBAction)toggleShowImages:(id)sender;
|
- (IBAction)toggleShowImages:(id)sender;
|
||||||
|
- (IBAction)toggleShowHiddenText:(id)sender;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
|
@ -185,6 +185,10 @@ static NSBitmapImageRep* ns_from_gfx(NonnullRefPtr<Gfx::Bitmap> bitmap_p)
|
||||||
[item setState:_preferences.show_images ? NSControlStateValueOn : NSControlStateValueOff];
|
[item setState:_preferences.show_images ? NSControlStateValueOn : NSControlStateValueOff];
|
||||||
return _doc ? YES : NO;
|
return _doc ? YES : NO;
|
||||||
}
|
}
|
||||||
|
if ([item action] == @selector(toggleShowHiddenText:)) {
|
||||||
|
[item setState:_preferences.show_hidden_text ? NSControlStateValueOn : NSControlStateValueOff];
|
||||||
|
return _doc ? YES : NO;
|
||||||
|
}
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,6 +232,14 @@ static NSBitmapImageRep* ns_from_gfx(NonnullRefPtr<Gfx::Bitmap> bitmap_p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (IBAction)toggleShowHiddenText:(id)sender
|
||||||
|
{
|
||||||
|
if (_doc) {
|
||||||
|
_preferences.show_hidden_text = !_preferences.show_hidden_text;
|
||||||
|
[self invalidateCachedBitmap];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)keyDown:(NSEvent*)event
|
- (void)keyDown:(NSEvent*)event
|
||||||
{
|
{
|
||||||
// Calls moveLeft: or moveRight: below.
|
// Calls moveLeft: or moveRight: below.
|
||||||
|
|
|
@ -26,6 +26,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||||
- (IBAction)toggleClipPaths:(id)sender;
|
- (IBAction)toggleClipPaths:(id)sender;
|
||||||
- (IBAction)toggleClipText:(id)sender;
|
- (IBAction)toggleClipText:(id)sender;
|
||||||
- (IBAction)toggleShowImages:(id)sender;
|
- (IBAction)toggleShowImages:(id)sender;
|
||||||
|
- (IBAction)toggleShowHiddenText:(id)sender;
|
||||||
- (IBAction)showGoToPageDialog:(id)sender;
|
- (IBAction)showGoToPageDialog:(id)sender;
|
||||||
|
|
||||||
- (void)pdfDidInitialize;
|
- (void)pdfDidInitialize;
|
||||||
|
|
|
@ -164,6 +164,11 @@
|
||||||
[_pdfView toggleShowImages:sender];
|
[_pdfView toggleShowImages:sender];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (IBAction)toggleShowHiddenText:(id)sender
|
||||||
|
{
|
||||||
|
[_pdfView toggleShowHiddenText:sender];
|
||||||
|
}
|
||||||
|
|
||||||
- (IBAction)showGoToPageDialog:(id)sender
|
- (IBAction)showGoToPageDialog:(id)sender
|
||||||
{
|
{
|
||||||
auto alert = [[NSAlert alloc] init];
|
auto alert = [[NSAlert alloc] init];
|
||||||
|
|
|
@ -694,6 +694,12 @@
|
||||||
<action selector="toggleShowImages:" target="-1" id="mNE-9J-Nle"/>
|
<action selector="toggleShowImages:" target="-1" id="mNE-9J-Nle"/>
|
||||||
</connections>
|
</connections>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
|
<menuItem title="Show Hidden Text" id="PhM-XC-ExK">
|
||||||
|
<modifierMask key="keyEquivalentModifierMask"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="toggleShowHiddenText:" target="-1" id="7iT-L2-Jd1"/>
|
||||||
|
</connections>
|
||||||
|
</menuItem>
|
||||||
</items>
|
</items>
|
||||||
</menu>
|
</menu>
|
||||||
</menuItem>
|
</menuItem>
|
||||||
|
|
|
@ -48,6 +48,7 @@ PDFViewer::PDFViewer()
|
||||||
m_page_view_mode = static_cast<PageViewMode>(Config::read_i32("PDFViewer"sv, "Display"sv, "PageMode"sv, 0));
|
m_page_view_mode = static_cast<PageViewMode>(Config::read_i32("PDFViewer"sv, "Display"sv, "PageMode"sv, 0));
|
||||||
m_rendering_preferences.show_clipping_paths = Config::read_bool("PDFViewer"sv, "Rendering"sv, "ShowClippingPaths"sv, false);
|
m_rendering_preferences.show_clipping_paths = Config::read_bool("PDFViewer"sv, "Rendering"sv, "ShowClippingPaths"sv, false);
|
||||||
m_rendering_preferences.show_images = Config::read_bool("PDFViewer"sv, "Rendering"sv, "ShowImages"sv, true);
|
m_rendering_preferences.show_images = Config::read_bool("PDFViewer"sv, "Rendering"sv, "ShowImages"sv, true);
|
||||||
|
m_rendering_preferences.show_hidden_text = Config::read_bool("PDFViewer"sv, "Rendering"sv, "ShowHiddenText"sv, false);
|
||||||
m_rendering_preferences.show_diagnostics = Config::read_bool("PDFViewer"sv, "Rendering"sv, "ShowDiagnostics"sv, false);
|
m_rendering_preferences.show_diagnostics = Config::read_bool("PDFViewer"sv, "Rendering"sv, "ShowDiagnostics"sv, false);
|
||||||
m_rendering_preferences.clip_images = Config::read_bool("PDFViewer"sv, "Rendering"sv, "ClipImages"sv, true);
|
m_rendering_preferences.clip_images = Config::read_bool("PDFViewer"sv, "Rendering"sv, "ClipImages"sv, true);
|
||||||
m_rendering_preferences.clip_paths = Config::read_bool("PDFViewer"sv, "Rendering"sv, "ClipPaths"sv, true);
|
m_rendering_preferences.clip_paths = Config::read_bool("PDFViewer"sv, "Rendering"sv, "ClipPaths"sv, true);
|
||||||
|
@ -192,6 +193,13 @@ void PDFViewer::set_show_images(bool show_images)
|
||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PDFViewer::set_show_hidden_text(bool show_hidden_text)
|
||||||
|
{
|
||||||
|
m_rendering_preferences.show_hidden_text = show_hidden_text;
|
||||||
|
Config::write_bool("PDFViewer"sv, "Rendering"sv, "ShowHiddenText"sv, show_hidden_text);
|
||||||
|
update();
|
||||||
|
}
|
||||||
|
|
||||||
void PDFViewer::set_clip_images(bool clip_images)
|
void PDFViewer::set_clip_images(bool clip_images)
|
||||||
{
|
{
|
||||||
m_rendering_preferences.clip_images = clip_images;
|
m_rendering_preferences.clip_images = clip_images;
|
||||||
|
|
|
@ -68,6 +68,8 @@ public:
|
||||||
void set_show_clipping_paths(bool);
|
void set_show_clipping_paths(bool);
|
||||||
bool show_images() const { return m_rendering_preferences.show_images; }
|
bool show_images() const { return m_rendering_preferences.show_images; }
|
||||||
void set_show_images(bool);
|
void set_show_images(bool);
|
||||||
|
bool show_hidden_text() const { return m_rendering_preferences.show_hidden_text; }
|
||||||
|
void set_show_hidden_text(bool);
|
||||||
bool clip_images() const { return m_rendering_preferences.clip_images; }
|
bool clip_images() const { return m_rendering_preferences.clip_images; }
|
||||||
void set_clip_images(bool);
|
void set_clip_images(bool);
|
||||||
bool clip_paths() const { return m_rendering_preferences.clip_paths; }
|
bool clip_paths() const { return m_rendering_preferences.clip_paths; }
|
||||||
|
|
|
@ -271,6 +271,11 @@ ErrorOr<void> PDFViewerWidget::initialize_menubar(GUI::Window& window)
|
||||||
});
|
});
|
||||||
toggle_show_images->set_checked(m_viewer->show_images());
|
toggle_show_images->set_checked(m_viewer->show_images());
|
||||||
debug_menu->add_action(toggle_show_images);
|
debug_menu->add_action(toggle_show_images);
|
||||||
|
auto toggle_show_hidden_text = GUI::Action::create_checkable("Show &Hidden Text", [&](auto& action) {
|
||||||
|
m_viewer->set_show_hidden_text(action.is_checked());
|
||||||
|
});
|
||||||
|
toggle_show_hidden_text->set_checked(m_viewer->show_hidden_text());
|
||||||
|
debug_menu->add_action(toggle_show_hidden_text);
|
||||||
auto toggle_clip_images = GUI::Action::create_checkable("Clip I&mages", [&](auto& action) {
|
auto toggle_clip_images = GUI::Action::create_checkable("Clip I&mages", [&](auto& action) {
|
||||||
m_viewer->set_clip_images(action.is_checked());
|
m_viewer->set_clip_images(action.is_checked());
|
||||||
});
|
});
|
||||||
|
|
|
@ -71,8 +71,10 @@ PDFErrorOr<Gfx::FloatPoint> SimpleFont::draw_string(Gfx::Painter& painter, Gfx::
|
||||||
else
|
else
|
||||||
glyph_width = font_size * m_missing_width * m_font_matrix.x_scale();
|
glyph_width = font_size * m_missing_width * m_font_matrix.x_scale();
|
||||||
|
|
||||||
Gfx::FloatPoint glyph_render_position = text_rendering_matrix.map(glyph_position);
|
if (renderer.text_state().rendering_mode != TextRenderingMode::Invisible || renderer.show_hidden_text()) {
|
||||||
TRY(draw_glyph(painter, glyph_render_position, glyph_width, char_code, renderer));
|
Gfx::FloatPoint glyph_render_position = text_rendering_matrix.map(glyph_position);
|
||||||
|
TRY(draw_glyph(painter, glyph_render_position, glyph_width, char_code, renderer));
|
||||||
|
}
|
||||||
|
|
||||||
// glyph_width is scaled by `text_rendering_matrix.x_scale() * renderer.text_state().font_size / horizontal_scaling`,
|
// glyph_width is scaled by `text_rendering_matrix.x_scale() * renderer.text_state().font_size / horizontal_scaling`,
|
||||||
// but it should only be scaled by `renderer.text_state().font_size`.
|
// but it should only be scaled by `renderer.text_state().font_size`.
|
||||||
|
|
|
@ -478,8 +478,10 @@ PDFErrorOr<Gfx::FloatPoint> Type0Font::draw_string(Gfx::Painter& painter, Gfx::F
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Gfx::FloatPoint glyph_render_position = text_rendering_matrix.map(glyph_position - Gfx::FloatPoint { position_vector_x, position_vector_y });
|
if (renderer.text_state().rendering_mode != TextRenderingMode::Invisible || renderer.show_hidden_text()) {
|
||||||
TRY(m_cid_font_type->draw_glyph(painter, glyph_render_position, glyph_width, cid, renderer));
|
Gfx::FloatPoint glyph_render_position = text_rendering_matrix.map(glyph_position - Gfx::FloatPoint { position_vector_x, position_vector_y });
|
||||||
|
TRY(m_cid_font_type->draw_glyph(painter, glyph_render_position, glyph_width, cid, renderer));
|
||||||
|
}
|
||||||
|
|
||||||
// glyph_width is scaled by `text_rendering_matrix.x_scale() * renderer.text_state().font_size / horizontal_scaling`,
|
// glyph_width is scaled by `text_rendering_matrix.x_scale() * renderer.text_state().font_size / horizontal_scaling`,
|
||||||
// but it should only be scaled by `renderer.text_state().font_size`.
|
// but it should only be scaled by `renderer.text_state().font_size`.
|
||||||
|
|
|
@ -89,6 +89,7 @@ struct GraphicsState {
|
||||||
struct RenderingPreferences {
|
struct RenderingPreferences {
|
||||||
bool show_clipping_paths { false };
|
bool show_clipping_paths { false };
|
||||||
bool show_images { true };
|
bool show_images { true };
|
||||||
|
bool show_hidden_text { false };
|
||||||
bool show_diagnostics { false };
|
bool show_diagnostics { false };
|
||||||
|
|
||||||
bool clip_images { true };
|
bool clip_images { true };
|
||||||
|
@ -121,6 +122,8 @@ public:
|
||||||
|
|
||||||
PDFErrorOr<void> render_type3_glyph(Gfx::FloatPoint, StreamObject const&, Gfx::AffineTransform const&, Optional<NonnullRefPtr<DictObject>>);
|
PDFErrorOr<void> render_type3_glyph(Gfx::FloatPoint, StreamObject const&, Gfx::AffineTransform const&, Optional<NonnullRefPtr<DictObject>>);
|
||||||
|
|
||||||
|
bool show_hidden_text() const { return m_rendering_preferences.show_hidden_text; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Renderer(RefPtr<Document>, Page const&, RefPtr<Gfx::Bitmap>, Color background_color, RenderingPreferences);
|
Renderer(RefPtr<Document>, Page const&, RefPtr<Gfx::Bitmap>, Color background_color, RenderingPreferences);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue