⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 230746 in webkit


Ignore:
Timestamp:
Apr 17, 2018, 7:50:25 PM (8 years ago)
Author:
Wenson Hsieh
Message:

[Extra zoom mode] Double tap to zoom should account for text legibility in extra zoom mode
https://bugs.webkit.org/show_bug.cgi?id=184631
<rdar://problem/39303706>

Reviewed by Tim Horton.

Source/WebKit:

Implement the text legibility heuristic alluded to in r230506 by iterating through text runs in the document (up
to a maximum of 200) and building a histogram of font sizes that appear in the document, where each tally
represents a character.

The first and second text legibility zoom scales are then computed based on the zoom scales needed to
make 50% and 90% of the text legible, respectively. Here, a zoom scale that makes text legible is such that the
text would have an apparent font size of a hard-coded constant (currently, 12) after zooming. This means the
first and second text legibility scales may end up being close to one another, or even the same (in the case
where there is only a single font size in the entire document). In this case, we just snap the first scale to
the second, so that double tapping will only toggle between two zoom scales. In another case where the document
has no text (e.g. an image document), we just fall back to a zoom scale of 1.

Test: fast/events/extrazoom/double-tap-to-zoom-on-full-width-text.html

  • WebProcess/WebPage/ViewGestureGeometryCollector.cpp:

(WebKit::ViewGestureGeometryCollector::computeTextLegibilityScales):

LayoutTests:

Add a layout test to check that double tap to zoom works in extra zoom mode, even when text spans the entire
width of the document.

  • TestExpectations:
  • fast/events/extrazoom/double-tap-to-zoom-on-full-width-text-expected.txt: Added.
  • fast/events/extrazoom/double-tap-to-zoom-on-full-width-text.html: Added.
  • resources/basic-gestures.js:

Add a helper method to double tap at a given location, and wait for zooming to finish.

(return.new.Promise):

Location:
trunk
Files:
3 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r230738 r230746  
     12018-04-17  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [Extra zoom mode] Double tap to zoom should account for text legibility in extra zoom mode
     4        https://bugs.webkit.org/show_bug.cgi?id=184631
     5        <rdar://problem/39303706>
     6
     7        Reviewed by Tim Horton.
     8
     9        Add a layout test to check that double tap to zoom works in extra zoom mode, even when text spans the entire
     10        width of the document.
     11
     12        * TestExpectations:
     13        * fast/events/extrazoom/double-tap-to-zoom-on-full-width-text-expected.txt: Added.
     14        * fast/events/extrazoom/double-tap-to-zoom-on-full-width-text.html: Added.
     15        * resources/basic-gestures.js:
     16
     17        Add a helper method to double tap at a given location, and wait for zooming to finish.
     18
     19        (return.new.Promise):
     20
    1212018-04-17  Tadeu Zagallo  <tzagallo@apple.com>
    222
  • trunk/LayoutTests/TestExpectations

    r230736 r230746  
    2626fast/visual-viewport/ios/ [ Skip ]
    2727fast/events/ios [ Skip ]
     28fast/events/extrazoom [ Skip ]
    2829fast/events/touch/ios [ Skip ]
    2930fast/history/ios [ Skip ]
  • trunk/LayoutTests/resources/basic-gestures.js

    r230527 r230746  
    77                    uiController.uiScriptComplete();
    88                }
     9            })();`, resolve);
     10    });
     11}
     12
     13function doubleTapToZoomAtPoint(x, y)
     14{
     15    return new Promise(resolve => {
     16        testRunner.runUIScript(`
     17            (function() {
     18                uiController.didEndZoomingCallback = () => uiController.uiScriptComplete();
     19                uiController.singleTapAtPoint(${x}, ${y}, () => { });
     20                uiController.singleTapAtPoint(${x}, ${y}, () => { });
    921            })();`, resolve);
    1022    });
  • trunk/Source/WebKit/ChangeLog

    r230745 r230746  
     12018-04-17  Wenson Hsieh  <wenson_hsieh@apple.com>
     2
     3        [Extra zoom mode] Double tap to zoom should account for text legibility in extra zoom mode
     4        https://bugs.webkit.org/show_bug.cgi?id=184631
     5        <rdar://problem/39303706>
     6
     7        Reviewed by Tim Horton.
     8
     9        Implement the text legibility heuristic alluded to in r230506 by iterating through text runs in the document (up
     10        to a maximum of 200) and building a histogram of font sizes that appear in the document, where each tally
     11        represents a character.
     12
     13        The first and second text legibility zoom scales are then computed based on the zoom scales needed to
     14        make 50% and 90% of the text legible, respectively. Here, a zoom scale that makes text legible is such that the
     15        text would have an apparent font size of a hard-coded constant (currently, 12) after zooming. This means the
     16        first and second text legibility scales may end up being close to one another, or even the same (in the case
     17        where there is only a single font size in the entire document). In this case, we just snap the first scale to
     18        the second, so that double tapping will only toggle between two zoom scales. In another case where the document
     19        has no text (e.g. an image document), we just fall back to a zoom scale of 1.
     20
     21        Test: fast/events/extrazoom/double-tap-to-zoom-on-full-width-text.html
     22
     23        * WebProcess/WebPage/ViewGestureGeometryCollector.cpp:
     24        (WebKit::ViewGestureGeometryCollector::computeTextLegibilityScales):
     25
    1262018-04-17  Megan Gardner  <megan_gardner@apple.com>
    227
  • trunk/Source/WebKit/WebProcess/WebPage/ViewGestureGeometryCollector.cpp

    r230506 r230746  
    2727#include "ViewGestureGeometryCollector.h"
    2828
     29#include "Logging.h"
    2930#include "ViewGestureGeometryCollectorMessages.h"
    3031#include "WebCoreArgumentCoders.h"
     
    3233#include "WebPage.h"
    3334#include "WebProcess.h"
     35#include <WebCore/FontCascade.h>
    3436#include <WebCore/Frame.h>
    3537#include <WebCore/FrameView.h>
    3638#include <WebCore/HTMLImageElement.h>
     39#include <WebCore/HTMLTextFormControlElement.h>
    3740#include <WebCore/HitTestResult.h>
    3841#include <WebCore/ImageDocument.h>
    3942#include <WebCore/RenderView.h>
     43#include <WebCore/TextIterator.h>
    4044
    4145#if PLATFORM(IOS)
     
    129133#if PLATFORM(IOS)
    130134
     135struct FontSizeAndCount {
     136    unsigned fontSize;
     137    unsigned count;
     138};
     139
    131140std::optional<std::pair<double, double>> ViewGestureGeometryCollector::computeTextLegibilityScales(double& viewportMinimumScale, double& viewportMaximumScale)
    132141{
    133     static const double defaultMaximumTextLegibilityScale = 1;
     142    static const unsigned fontSizeBinningInterval = 2;
     143    static const double maximumNumberOfTextRunsToConsider = 200;
     144
     145    static const double targetLegibilityFontSize = 12;
     146    static const double firstTextLegibilityScaleRatio = 0.5;
     147    static const double secondTextLegibilityScaleRatio = 0.1;
     148    static const double minimumDifferenceBetweenTextLegibilityScales = 0.2;
     149    static const double fallbackTextLegibilityScale = 1;
    134150
    135151    computeMinimumAndMaximumViewportScales(viewportMinimumScale, viewportMaximumScale);
     
    143159    document->updateLayoutIgnorePendingStylesheets();
    144160
    145     // FIXME: Determine appropriate text legibility scales by examining text runs in the document. For now, hard code the second text legibility scale to be 1,
    146     // and set the first text legibility scale to be the halfway point between the initial scale and 1.
    147     double firstTextLegibilityScale = clampTo<double>((m_webPage.viewportConfiguration().initialScale() + defaultMaximumTextLegibilityScale) / 2, viewportMinimumScale, viewportMaximumScale);
    148     double secondTextLegibilityScale = clampTo<double>(defaultMaximumTextLegibilityScale, viewportMinimumScale, viewportMaximumScale);
     161    auto documentRange = Range::create(*document, {{ document->documentElement(), Position::PositionIsBeforeAnchor }}, {{ document->documentElement(), Position::PositionIsAfterAnchor }});
     162    HashSet<Node*> allTextNodes;
     163    HashMap<unsigned, unsigned> fontSizeToCountMap;
     164    unsigned numberOfIterations = 0;
     165    unsigned totalSampledTextLength = 0;
     166
     167    for (TextIterator documentTextIterator { documentRange.ptr(), TextIteratorEntersTextControls }; !documentTextIterator.atEnd(); documentTextIterator.advance()) {
     168        if (++numberOfIterations >= maximumNumberOfTextRunsToConsider)
     169            break;
     170
     171        if (!is<Text>(documentTextIterator.node()))
     172            continue;
     173
     174        auto& textNode = downcast<Text>(*documentTextIterator.node());
     175        auto textLength = textNode.length();
     176        if (!textLength || !textNode.renderer() || allTextNodes.contains(&textNode))
     177            continue;
     178
     179        allTextNodes.add(&textNode);
     180
     181        unsigned fontSizeBin = fontSizeBinningInterval * round(textNode.renderer()->style().fontCascade().size() / fontSizeBinningInterval);
     182        auto entry = fontSizeToCountMap.find(fontSizeBin);
     183        fontSizeToCountMap.set(fontSizeBin, textLength + (entry == fontSizeToCountMap.end() ? 0 : entry->value));
     184        totalSampledTextLength += textLength;
     185    }
     186
     187    Vector<FontSizeAndCount> sortedFontSizesAndCounts;
     188    sortedFontSizesAndCounts.reserveCapacity(fontSizeToCountMap.size());
     189    for (auto& entry : fontSizeToCountMap)
     190        sortedFontSizesAndCounts.append({ entry.key, entry.value });
     191
     192    std::sort(sortedFontSizesAndCounts.begin(), sortedFontSizesAndCounts.end(), [] (auto& first, auto& second) {
     193        return first.fontSize < second.fontSize;
     194    });
     195
     196    double firstTextLegibilityScale = 0;
     197    double secondTextLegibilityScale = 0;
     198    double currentSampledTextLength = 0;
     199    for (auto& fontSizeAndCount : sortedFontSizesAndCounts) {
     200        currentSampledTextLength += fontSizeAndCount.count;
     201        double ratioOfTextUnderCurrentFontSize = currentSampledTextLength / totalSampledTextLength;
     202        LOG(ViewGestures, "About %.2f%% of text is smaller than font size %tu", ratioOfTextUnderCurrentFontSize * 100, fontSizeAndCount.fontSize);
     203        if (!firstTextLegibilityScale && ratioOfTextUnderCurrentFontSize >= firstTextLegibilityScaleRatio)
     204            firstTextLegibilityScale = targetLegibilityFontSize / fontSizeAndCount.fontSize;
     205        if (!secondTextLegibilityScale && ratioOfTextUnderCurrentFontSize >= secondTextLegibilityScaleRatio)
     206            secondTextLegibilityScale = targetLegibilityFontSize / fontSizeAndCount.fontSize;
     207    }
     208
     209    if (sortedFontSizesAndCounts.isEmpty()) {
     210        firstTextLegibilityScale = fallbackTextLegibilityScale;
     211        secondTextLegibilityScale = fallbackTextLegibilityScale;
     212    } else if (secondTextLegibilityScale - firstTextLegibilityScale < minimumDifferenceBetweenTextLegibilityScales)
     213        firstTextLegibilityScale = secondTextLegibilityScale;
     214
     215    secondTextLegibilityScale = clampTo<double>(secondTextLegibilityScale, viewportMinimumScale, viewportMaximumScale);
     216    firstTextLegibilityScale = clampTo<double>(firstTextLegibilityScale, viewportMinimumScale, viewportMaximumScale);
     217
     218    LOG(ViewGestures, "The computed text legibility scales are: (%.2f, %.2f)", firstTextLegibilityScale, secondTextLegibilityScale);
    149219
    150220    m_cachedTextLegibilityScales = std::optional<std::pair<double, double>> {{ firstTextLegibilityScale, secondTextLegibilityScale }};
Note: See TracChangeset for help on using the changeset viewer.