Skip to content

wiera updates#1

Open
username77 wants to merge 44 commits intousername77:masterfrom
wiera987:master
Open

wiera updates#1
username77 wants to merge 44 commits intousername77:masterfrom
wiera987:master

Conversation

@username77
Copy link
Owner

No description provided.

wiera987 and others added 30 commits May 6, 2019 10:58
- Cached PageData, but PDFForm not tested.
This issue occurs when you zoom too far and only half a page or less appears on the screen.
# Conflicts:
#	PdfiumViewer/NativeMethods.Pdfium.cs
#	PdfiumViewer/PdfFile.cs
  Add the Text Mode button to copy text.
Viewer:
  When dragging the mouse outside the window, it scrolls while selecting text.
  Loosen the judgment of the Y coordinate while the mouse is moving.
Build tool changed. Visual studio 2022 / .NET Framework 4.8.
…during initialization of controls including PdfViewer.
Get the start page and end page of the selected bookmark node.
Checks if the specified page has any markers.
@gemini-code-assist
Copy link

Summary of Changes

Hello @username77, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request delivers substantial upgrades to the PdfiumViewer library, focusing on improving user interaction and refining its internal architecture. Users will benefit from a more robust text selection mode with visual feedback, a more stable and precise zooming experience, and a comprehensive set of tools for managing PDF bookmarks. The project also received an update to target .NET Framework 4.8, and its internal page data caching mechanism was optimized for better overall performance and flexibility.

Highlights

  • Enhanced Text Selection and Zooming: Introduced a new 'Text Mode' button in the demo application to toggle between panning and text selection. The text selection mechanism has been refined with improved cursor handling and automatic scrolling. Zooming functionality now uses double-precision coordinates to prevent rounding errors during repeated magnification, ensuring more precise focus-based zooming.
  • Advanced Bookmark Management: The bookmark panel now features a dedicated toolbar with options to expand/collapse top-level, all, or current bookmarks, and a button to close the panel. The logic for bookmark navigation and page range determination has been significantly improved.
  • .NET Framework Upgrade: The demo and WPF demo projects have been upgraded to target .NET Framework 4.8, along with corresponding updates to project files and auto-generated resource files.
  • Internal Architecture Improvements: Refactored the internal handling of PDF page data from a single-page cache to a list of page data objects, which enhances performance and consistency. New capabilities for drawing text outlines and comparison bounds, including animated flashing for text spans, have also been added.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces significant enhancements and refactorings across the PdfiumViewer library, primarily focusing on improved text selection, bookmark management, and rendering accuracy. Key changes include the addition of a 'Text Mode' button and functionality, a new PdfCursorMode enum (a breaking change) with a 'Bounds' option, and a CompareBounds property for defining comparison areas. The CustomScrollControl was refactored to use double-precision coordinates to prevent rounding errors during magnification and includes a robustness check for zero height. The page data caching mechanism in PdfFile.cs was updated to cache all pages, improving performance but potentially increasing memory usage, with corresponding updates to the dispose logic. The PdfRenderer component received extensive updates, including a ResetRenderer method for state management, PointToPdfRounded for precise coordinate conversion, and corrections to rotation logic. New drawing methods (DrawCompareBounds, DrawTextOutline, DrawTextSpans) were added for visual feedback, along with animated text highlighting using SetFlashTextSpans and CalcFlashTextAlpha. Bookmark functionality was greatly expanded with a new toolstrip, allowing for comprehensive control over bookmark tree expansion/collapse, selection based on current page, and page range calculation, including a clever EnsureVisibleWithoutRightScrolling method. Several breaking changes were noted, such as the renaming of PdfViewerCursorMode and the removal of GetTextRectangles from IPdfDocument, requiring careful migration. Additionally, build settings were updated to target .NET Framework 4.8 and strong-naming was disabled.

Comment on lines +7 to +12
public enum PdfCursorMode
{
Pan,
TextSelection,
Bounds
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

The renaming of PdfViewerCursorMode to PdfCursorMode and the addition of the Bounds enum value is a breaking change for any external code that references the old enum name. While Bounds adds new functionality, the rename requires careful migration. Ensure that all references to the old enum name are updated throughout the codebase and in any consuming projects.

Comment on lines +218 to +224
public PdfCursorMode CursorMode
{
get { return _cursorMode; }
set
{
_cursorMode = value;
MousePanningEnabled = _cursorMode == PdfViewerCursorMode.Pan;
MousePanningEnabled = _cursorMode == PdfCursorMode.Pan;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The change of CursorMode to use the new PdfCursorMode enum is a breaking change. While it allows for new cursor modes like Bounds, it will require updates in any code that previously referenced PdfViewerCursorMode. Ensure this transition is handled smoothly in documentation and examples.

Comment on lines +17 to +21
<SignAssembly>false</SignAssembly>
</PropertyGroup>
<PropertyGroup>
<AssemblyOriginatorKeyFile>Key.snk</AssemblyOriginatorKeyFile>
<AssemblyOriginatorKeyFile>
</AssemblyOriginatorKeyFile>

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Changing SignAssembly to false and clearing AssemblyOriginatorKeyFile means the assembly will no longer be strong-named. This can affect compatibility with other strong-named assemblies or deployment scenarios. Ensure this change is intentional and its implications are understood.

/// <param name="page">The page to get the rectangles from</param>
/// <returns>The rectangular areas occupied by a segment of text</returns>
List<PdfRectangle> GetTextRectangles(int page, int startIndex, int count);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The removal of the GetTextRectangles method from the IPdfDocument interface is a breaking change. Any external code that directly implements or consumes this interface and relies on this method will need to be updated. Ensure that this change is intentional and communicated to users of the library.

Comment on lines +451 to +454
if (preventPageRefresh == false)
{
_renderer.Page = ((PdfBookmark)e.Node.Tag).PageIndex;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The _bookmarks_AfterSelect event handler now correctly uses preventPageRefresh to avoid unnecessary page jumps when the TreeView's selection changes due to programmatic updates (e.g., during expand/collapse operations). This improves the responsiveness and predictability of the UI.

Comment on lines +457 to 483
private void _bookmarks_BeforeExpand(object sender, TreeViewCancelEventArgs e)
{
// AfterSelect event is fired when child node has focus.
preventPageRefresh = true;
}

private void _bookmarks_AfterExpand(object sender, TreeViewEventArgs e)
{
// AfterSelect event is fired when child node has focus.
preventPageRefresh = false;

// Select a bookmark for the renderer page.
bookmarkPage = -1;
SelectBookmarkForPage(_renderer.Page);
}

private void _bookmarks_BeforeCollapse(object sender, TreeViewCancelEventArgs e)
{
// AfterSelect event is fired when child node has focus.
preventPageRefresh = true;
}

private void _bookmarks_AfterCollapse(object sender, TreeViewEventArgs e)
{
// AfterSelect event is fired when child node has focus.
preventPageRefresh = false;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The _bookmarks_BeforeExpand, _bookmarks_AfterExpand, _bookmarks_BeforeCollapse, and _bookmarks_AfterCollapse event handlers are crucial for managing the preventPageRefresh flag. This ensures that page changes are only triggered by explicit user selection, not by the TreeView's internal expansion/collapse logic.

Comment on lines +490 to +587
private void toolStripButtonExpand_Click(object sender, EventArgs e)
{
// Expand Top-Level
bool visible = _showBookmarks && _document != null && _document.Bookmarks.Count > 0;

if (visible)
{
foreach (TreeNode node in _bookmarks.Nodes)
{
node.Expand();
}

// Show selected nodes.
EnsureVisibleWithoutRightScrolling(_bookmarks.SelectedNode);
}
}

private void toolStripSplitButtonCollapse_ButtonClick(object sender, EventArgs e)
{
// Collapse Top-Level
bool visible = _showBookmarks && _document != null && _document.Bookmarks.Count > 0;

if (visible)
{
foreach (TreeNode node in _bookmarks.Nodes)
{
node.Collapse();
}
// Show selected nodes.
EnsureVisibleWithoutRightScrolling(_bookmarks.SelectedNode);
}
}

private void expandAllToolStripMenuItem_Click(object sender, EventArgs e)
{
// Expand All
_bookmarks.ExpandAll();
// Show selected nodes.
EnsureVisibleWithoutRightScrolling(_bookmarks.SelectedNode);
}

private void collapseAllToolStripMenuItem_Click(object sender, EventArgs e)
{
// Collapse All
CollapseChildrenNodes(_bookmarks.Nodes);
// Show selected nodes.
EnsureVisibleWithoutRightScrolling(_bookmarks.SelectedNode);
}

private void toolStripButtonExpandCurrent_Click(object sender, EventArgs e)
{
// Expand current bookmark
TreeNode validNode = null;

// Collapse all nodes initially
CollapseChildrenNodes(_bookmarks.Nodes);
GetPageNode(_renderer.Page, _bookmarks.Nodes, true, ref validNode);
ExpandParentNodes(validNode);

// Show selected nodes.
EnsureVisibleWithoutRightScrolling(_bookmarks.SelectedNode);
}

private void ExpandParentNodes(TreeNode node)
{
if (node != null)
{
node.Expand();
if (node.Parent != null)
{
ExpandParentNodes(node.Parent);
}
}
}

private void CollapseChildrenNodes(TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
if (node != null)
{
if (node.Nodes != null)
{
CollapseChildrenNodes(node.Nodes);
}
node.Collapse();
}
}
}

private void EnsureVisibleWithoutRightScrolling(TreeNode node)
{
// we do the standard call..
node?.EnsureVisible();

// ..and afterwards we scroll to the left again!
SendMessage(_bookmarks.Handle, WM_HSCROLL, SB_LEFT, 0);
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The new toolstrip button event handlers (toolStripButtonExpand_Click, toolStripSplitButtonCollapse_ButtonClick, expandAllToolStripMenuItem_Click, collapseAllToolStripMenuItem_Click, toolStripButtonExpandCurrent_Click, toolStripButtonClose_Click) and their helper methods (ExpandParentNodes, CollapseChildrenNodes, EnsureVisibleWithoutRightScrolling) provide comprehensive control over bookmark tree manipulation. The EnsureVisibleWithoutRightScrolling is particularly clever for maintaining horizontal scroll position.

y = minY;

SetDisplayRectLocation(x, y);
SetDisplayRectLocation(x, y, false);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Changing SetDisplayRectLocation to always pass false for preserveContents when setting the display rectangle size might have performance implications or visual effects. If preserveContents is intended to optimize redrawing, forcing false could lead to unnecessary full redraws. Consider if this is the desired behavior in all scenarios, or if preserveContents should be determined dynamically.

Comment on lines +128 to +131
if (fullClient.Height == 0)
{
return false;
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Adding a check for fullClient.Height == 0 is a good defensive programming practice to prevent potential division-by-zero errors or other layout issues when the control has no height. This improves the robustness of the ApplyScrollbarChanges method.

Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6a6075aabe

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 247 to 251
if (!MousePanningEnabled || e.Button != MouseButtons.Left || !_canPan)
return;

Capture = true;
_capture = true;
_dragStart = e.Location;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Restore mouse capture during panning

The drag state now only flips the private _capture flag and never calls Capture = true. If the user drags outside the control and releases the mouse button, WinForms will not deliver OnMouseUp back to this control, leaving _capture stuck true and causing panning on later mouse moves even with no button pressed. This shows up any time a drag exits the control bounds; consider re‑enabling mouse capture (or resetting on mouse leave) so the control always receives the button‑up event.

Useful? React with 👍 / 👎.

Comment on lines +293 to +297
int rect_count = NativeMethods.FPDFText_CountRects(pageData.TextPage, textSpan.Offset, textSpan.Length);

for (int i = 0; i < rect_count; i++)
{
NativeMethods.FPDFText_GetRect(pageData.TextPage, i, out var left, out var top, out var right, out var bottom);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep CountRects/GetRect under one lock

Here FPDFText_CountRects and FPDFText_GetRect are invoked in separate, individually locked calls. PDFium’s GetRect uses internal state set by the last CountRects, so without a single shared lock another thread can interleave its own CountRects call and cause rectangles to be read from the wrong range or throw. This becomes visible under concurrent text‑highlight or search usage; use the existing FPDFText_GetRectangles helper or wrap both calls in one lock.

Useful? React with 👍 / 👎.

Copy link
Owner Author

@username77 username77 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

pdfile performance

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants