LayoutTests/ChangeLog

 12011-09-05 Kenichi Ishibashi <bashi@chromium.org>
 2
 3 [Chromium] Implement font shaping with font-feature-settings on Windows
 4 https://bugs.webkit.org/show_bug.cgi?id=65904
 5
 6 Adds expectations of css3/font-feature-settings-rendering.html for Chromium win port.
 7
 8 Reviewed by NOBODY (OOPS!).
 9
 10 * platform/chromium-win/css3/font-feature-settings-rendering-expected.png: Added.
 11 * platform/chromium-win/css3/font-feature-settings-rendering-expected.txt: Added.
 12 * platform/chromium/test_expectations.txt: VISTA and WIN7 should pass css3/font-feature-settings-rendering.html.
 13
1142011-09-05 John Knottenbelt <jknotten@chromium.org>
215
316 Take pageScaleFactor into account for MouseRelatedEvents.

LayoutTests/platform/chromium-win/css3/font-feature-settings-rendering-expected.png


Added

8fe50c0062febc6fcfc99e7fbd1e2453

LayoutTests/platform/chromium-win/css3/font-feature-settings-rendering-expected.txt

 1layer at (0,0) size 800x600
 2 RenderView at (0,0) size 800x600
 3layer at (0,0) size 800x600
 4 RenderBlock {HTML} at (0,0) size 800x600
 5 RenderBody {BODY} at (8,8) size 784x584
 6 RenderBlock {P} at (0,0) size 784x40
 7 RenderText {#text} at (0,0) size 783x39
 8 text run at (0,0) width 235: "Test for font-feature-settings property. "
 9 text run at (235,0) width 548: "The first word of the following three words should be displayed like \"WebKit\", while others"
 10 text run at (0,20) width 217: "should be displayed as black boxes."
 11 RenderBlock {DIV} at (0,56) size 784x17
 12 RenderText {#text} at (0,0) size 30x16
 13 text run at (0,0) width 30: "WebKit"
 14 RenderBlock {DIV} at (0,73) size 784x17
 15 RenderText {#text} at (0,0) size 96x16
 16 text run at (0,0) width 96: "WebKit"
 17 RenderBlock {DIV} at (0,90) size 784x17
 18 RenderText {#text} at (0,0) size 96x16
 19 text run at (0,0) width 96: "WebKit"

LayoutTests/platform/chromium/test_expectations.txt

@@BUGWK65951 WIN DEBUG : webaudio/mixing.html = CRASH
35903590BUGWK65951 LINUX MAC DEBUG : webaudio/mixing.html = CRASH PASS
35913591BUGWK65951 LINUX MAC DEBUG : webaudio/test-basic.html = CRASH PASS
35923592
3593 BUGWK63796 MAC WIN : css3/font-feature-settings-rendering.html = MISSING FAIL
 3593BUGWK63796 MAC XP : css3/font-feature-settings-rendering.html = MISSING FAIL
35943594
35953595// New test in r93068
35963596BUGWK66268 WIN MAC : editing/deleting/regional-indicators.html = TEXT

Source/WebCore/ChangeLog

 12011-09-05 Kenichi Ishibashi <bashi@chromium.org>
 2
 3 [Chromium] Implement font shaping with font-feature-settings on Windows
 4 https://bugs.webkit.org/show_bug.cgi?id=65904
 5
 6 Reviewed by NOBODY (OOPS!).
 7
 8 Use Uniscribe's OpenType APIs to shape complex text to support -webkit-font-feature-settings property.
 9
 10 No new tests. css3/font-feature-settings-rendering.html should pass by this patch.
 11
 12 * platform/graphics/chromium/UniscribeHelper.cpp:
 13 (WebCore::loadOpenTypeFunctions): Added.
 14 (WebCore::UniscribeHelper::UniscribeHelper): Calls loadOpenTypeFunctions if needed.
 15 (WebCore::UniscribeHelper::fillRuns): Uses ScriptItemizeOpenType() if possible.
 16 (WebCore::UniscribeHelper::shape): Uses ScriptShapeOpenType() if possible.
 17 (WebCore::UniscribeHelper::fillShapes): Adds OpenType script tag as an argument.
 18 (WebCore::convertFeatureTag): Added.
 19 (WebCore::UniscribeHelper::setRangeProperties): Added.
 20 * platform/graphics/chromium/UniscribeHelper.h:
 21 * platform/graphics/chromium/UniscribeHelperTextRun.cpp:
 22 (WebCore::UniscribeHelperTextRun::UniscribeHelperTextRun): Calls setRangeProperties().
 23
1242011-09-05 Sheriff Bot <webkit.review.bot@gmail.com>
225
326 Unreviewed, rolling out r94537.

Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp

4141
4242namespace WebCore {
4343
 44// The function types for ScriptItemizeOpenType() and ScriptShapeOpenType().
 45// We want to use these functions for OpenType feature support, but we can't
 46// call them directly because usp10.dll does not always have them.
 47// Instead, we use GetProcAddress() to check whether we can actually use these
 48// function. If we can't use these functions, we substitute ScriptItemze() and
 49// ScriptShape().
 50typedef HRESULT (WINAPI *ScriptItemizeOpenTypeFunc)(const WCHAR*, int, int,
 51 const SCRIPT_CONTROL*,
 52 const SCRIPT_STATE*,
 53 SCRIPT_ITEM*,
 54 OPENTYPE_TAG*, int*);
 55typedef HRESULT (WINAPI *ScriptShapeOpenTypeFunc)(HDC, SCRIPT_CACHE*,
 56 SCRIPT_ANALYSIS*,
 57 OPENTYPE_TAG, OPENTYPE_TAG,
 58 int*, TEXTRANGE_PROPERTIES**,
 59 int, const WCHAR*, int, int,
 60 WORD*, SCRIPT_CHARPROP*,
 61 WORD*, SCRIPT_GLYPHPROP*,
 62 int*);
 63
 64static ScriptItemizeOpenTypeFunc sScriptItemizeOpenTypeFunc = 0;
 65static ScriptShapeOpenTypeFunc sScriptShapeOpenTypeFunc = 0;
 66static bool sOpenTypeFunctionsLoaded = false;
 67
 68static void loadOpenTypeFunctions()
 69{
 70 HMODULE hModule = GetModuleHandle(L"usp10");
 71 if (hModule) {
 72 sScriptItemizeOpenTypeFunc = reinterpret_cast<ScriptItemizeOpenTypeFunc>(GetProcAddress(hModule, "ScriptItemizeOpenType"));
 73 sScriptShapeOpenTypeFunc = reinterpret_cast<ScriptShapeOpenTypeFunc>(GetProcAddress(hModule, "ScriptShapeOpenType"));
 74 }
 75 sOpenTypeFunctionsLoaded = true;
 76}
 77
4478// HFONT is the 'incarnation' of 'everything' about font, but it's an opaque
4579// handle and we can't directly query it to make a new HFONT sharing
4680// its characteristics (height, style, etc) except for family name.

@@UniscribeHelper::UniscribeHelper(const UChar* input,
92126
93127{
94128 m_logfont.lfFaceName[0] = 0;
 129 if (!sOpenTypeFunctionsLoaded)
 130 loadOpenTypeFunctions();
95131}
96132
97133UniscribeHelper::~UniscribeHelper()

@@void UniscribeHelper::fillRuns()
438474{
439475 HRESULT hr;
440476 m_runs.resize(UNISCRIBE_HELPER_STACK_RUNS);
 477 m_scriptTags.resize(UNISCRIBE_HELPER_STACK_RUNS);
441478
442479 SCRIPT_STATE inputState;
443480 inputState.uBidiLevel = m_isRtl;

@@void UniscribeHelper::fillRuns()
492529 // It seems to be doing at least two passes, the first where it puts a
493530 // lot of intermediate data into our items, and the second where it
494531 // collates them.
495  hr = ScriptItemize(m_input, m_inputLength,
496  static_cast<int>(m_runs.size()) - 1, &inputControl,
497  &inputState,
498  &m_runs[0], &numberOfItems);
 532 if (sScriptItemizeOpenTypeFunc) {
 533 hr = sScriptItemizeOpenTypeFunc(m_input, m_inputLength,
 534 static_cast<int>(m_runs.size()) - 1,
 535 &inputControl, &inputState,
 536 &m_runs[0], &m_scriptTags[0],
 537 &numberOfItems);
 538 if (SUCCEEDED(hr)) {
 539 // Pack consecutive runs, the script tag of which are
 540 // SCRIPT_TAG_UNKNOWN, to reduce the number of runs.
 541 for (int i = 0; i < numberOfItems; ++i) {
 542 if (m_scriptTags[i] == SCRIPT_TAG_UNKNOWN) {
 543 int j = 1;
 544 while (i + j < numberOfItems && m_scriptTags[i + j] == SCRIPT_TAG_UNKNOWN)
 545 ++j;
 546 if (--j) {
 547 m_runs.remove(i + 1, j);
 548 m_scriptTags.remove(i + 1, j);
 549 numberOfItems -= j;
 550 }
 551 }
 552 }
 553 m_scriptTags.resize(numberOfItems);
 554 }
 555 } else {
 556 hr = ScriptItemize(m_input, m_inputLength,
 557 static_cast<int>(m_runs.size()) - 1,
 558 &inputControl, &inputState, &m_runs[0],
 559 &numberOfItems);
 560 }
499561 if (SUCCEEDED(hr)) {
500562 m_runs.resize(numberOfItems);
501563 break;

@@void UniscribeHelper::fillRuns()
507569 }
508570 // There was not enough items for it to write into, expand.
509571 m_runs.resize(m_runs.size() * 2);
 572 m_scriptTags.resize(m_runs.size());
510573 }
511574}
512575

@@bool UniscribeHelper::shape(const UChar* input,
514577 int itemLength,
515578 int numGlyphs,
516579 SCRIPT_ITEM& run,
 580 OPENTYPE_TAG scriptTag,
517581 Shaping& shaping)
518582{
519583 HFONT hfont = m_hfont;
520584 SCRIPT_CACHE* scriptCache = m_scriptCache;
521585 SCRIPT_FONTPROPERTIES* fontProperties = m_fontProperties;
 586 Vector<SCRIPT_CHARPROP, UNISCRIBE_HELPER_STACK_CHARS> charProps;
 587 Vector<SCRIPT_GLYPHPROP, UNISCRIBE_HELPER_STACK_CHARS> glyphProps;
522588 int ascent = m_ascent;
523589 WORD spaceGlyph = m_spaceGlyph;
524590 HDC tempDC = 0;

@@bool UniscribeHelper::shape(const UChar* input,
541607 shaping.m_logs.resize(itemLength);
542608 shaping.m_glyphs.resize(numGlyphs);
543609 shaping.m_visualAttributes.resize(numGlyphs);
 610 charProps.resize(itemLength);
 611 glyphProps.resize(numGlyphs);
544612
545613#ifdef PURIFY
546614 // http://code.google.com/p/chromium/issues/detail?id=5309

@@bool UniscribeHelper::shape(const UChar* input,
561629 ZeroMemory(&shaping.m_glyphs[0],
562630 sizeof(shaping.m_glyphs[0]) * shaping.m_glyphs.size());
563631#endif
564 
565632 // Firefox sets SCRIPT_ANALYSIS.SCRIPT_STATE.fDisplayZWG to true
566633 // here. Is that what we want? It will display control characters.
567  hr = ScriptShape(tempDC, scriptCache, input, itemLength,
568  numGlyphs, &run.a,
569  &shaping.m_glyphs[0], &shaping.m_logs[0],
570  &shaping.m_visualAttributes[0], &generatedGlyphs);
 634 if (sScriptShapeOpenTypeFunc) {
 635 TEXTRANGE_PROPERTIES* rangeProps = m_featureRecords.size() ? &m_rangeProperties : 0;
 636 hr = sScriptShapeOpenTypeFunc(tempDC, scriptCache, &run.a,
 637 scriptTag, 0, &itemLength,
 638 &rangeProps, rangeProps ? 1 : 0,
 639 input, itemLength, numGlyphs,
 640 &shaping.m_logs[0], &charProps[0],
 641 &shaping.m_glyphs[0], &glyphProps[0],
 642 &generatedGlyphs);
 643 } else {
 644 hr = ScriptShape(tempDC, scriptCache, input, itemLength,
 645 numGlyphs, &run.a,
 646 &shaping.m_glyphs[0], &shaping.m_logs[0],
 647 &shaping.m_visualAttributes[0], &generatedGlyphs);
 648 }
571649 if (hr == E_PENDING) {
572650 // Allocate the DC.
573651 tempDC = GetDC(0);

@@bool UniscribeHelper::shape(const UChar* input,
664742 cleanup:
665743 shaping.m_glyphs.resize(generatedGlyphs);
666744 shaping.m_visualAttributes.resize(generatedGlyphs);
 745 // If we use ScriptShapeOpenType(), visual attributes information for each
 746 // characters are stored in |glyphProps[i].sva|.
 747 if (sScriptShapeOpenTypeFunc) {
 748 for (int i = 0; i < generatedGlyphs; ++i) {
 749 memcpy(&shaping.m_visualAttributes[i], &glyphProps[i].sva,
 750 sizeof(SCRIPT_VISATTR));
 751 }
 752 }
667753 shaping.m_advance.resize(generatedGlyphs);
668754 shaping.m_offsets.resize(generatedGlyphs);
669755 if (tempDC) {

@@void UniscribeHelper::fillShapes()
704790 // Convert a string to a glyph string trying the primary font, fonts in
705791 // the fallback list and then script-specific last resort font.
706792 Shaping& shaping = m_shapes[i];
707  if (!shape(&m_input[startItem], itemLength, numGlyphs, m_runs[i], shaping))
 793 if (!shape(&m_input[startItem], itemLength, numGlyphs, m_runs[i], m_scriptTags[i], shaping))
708794 continue;
709795
710796 // At the moment, the only time m_disableFontFallback is set is

@@void UniscribeHelper::fillShapes()
743829 // Some error we don't know how to handle. Nuke all of our data
744830 // since we can't deal with partially valid data later.
745831 m_runs.clear();
 832 m_scriptTags.clear();
746833 m_shapes.clear();
747834 m_screenOrder.clear();
748835 }

@@bool UniscribeHelper::containsMissingGlyphs(const Shaping& shaping,
9511038 return false;
9521039}
9531040
 1041static OPENTYPE_TAG convertFeatureTag(const String& tag)
 1042{
 1043 return ((tag[0] & 0xFF) | ((tag[1] & 0xFF) << 8) | ((tag[2] & 0xFF) << 16) | ((tag[3] & 0xFF) << 24));
 1044}
 1045
 1046void UniscribeHelper::setRangeProperties(const FontFeatureSettings* featureSettings)
 1047{
 1048 if (!featureSettings || !featureSettings->size()) {
 1049 m_featureRecords.resize(0);
 1050 return;
 1051 }
 1052
 1053 m_featureRecords.resize(featureSettings->size());
 1054 for (unsigned i = 0; i < featureSettings->size(); ++i) {
 1055 m_featureRecords[i].lParameter = featureSettings->at(i).value();
 1056 m_featureRecords[i].tagFeature = convertFeatureTag(featureSettings->at(i).tag());
 1057 }
 1058 m_rangeProperties.potfRecords = &m_featureRecords[0];
 1059 m_rangeProperties.cotfRecords = m_featureRecords.size();
 1060}
9541061
9551062} // namespace WebCore

Source/WebCore/platform/graphics/chromium/UniscribeHelper.h

@@class UniscribeTest_TooBig_Test; // A gunit test for UniscribeHelper.
4444
4545namespace WebCore {
4646
 47class FontFeatureSettings;
4748class GraphicsContext;
4849
4950#define UNISCRIBE_HELPER_STACK_RUNS 8
5051#define UNISCRIBE_HELPER_STACK_CHARS 32
 52#define UNISCRIBE_HELPER_FEATURES 4
5153
5254// This object should be safe to create & destroy frequently, as long as the
5355// caller preserves the script_cache when possible (this data may be slow to

@@public:
158160 m_disableFontFallback = true;
159161 }
160162
 163 // Set TEXTRANGE_PROPERTIES structure which contains
 164 // OpenType feature records generated from FontFeatureSettings.
 165 void setRangeProperties(const FontFeatureSettings*);
 166
161167 // You must call this after setting any options but before doing any
162168 // other calls like asking for widths or drawing.
163169 void init()

@@private:
358364 // by |input| comes from ScriptItemize and is supposed to contain
359365 // characters belonging to a single script aside from characters common to
360366 // all scripts (e.g. space).
361  bool shape(const UChar* input, int itemLength, int numGlyphs, SCRIPT_ITEM& run, Shaping&);
 367 bool shape(const UChar* input, int itemLength, int numGlyphs, SCRIPT_ITEM& run, OPENTYPE_TAG, Shaping&);
362368
363369 // Gets Windows font data for the next best font to try in the list
364370 // of fonts. When there's no more font available, returns false

@@private:
408414 Vector<SCRIPT_ITEM, UNISCRIBE_HELPER_STACK_RUNS> m_runs;
409415
410416 Vector<Shaping, UNISCRIBE_HELPER_STACK_RUNS> m_shapes;
 417 Vector<OPENTYPE_TAG, UNISCRIBE_HELPER_STACK_RUNS> m_scriptTags;
411418
412419 // This is a mapping between reading order and screen order for the items.
413420 // Uniscribe's items array are in reading order. For right-to-left text,

@@private:
417424 // gives the index into the |m_runs| and |m_shapes| arrays of each
418425 // subsequent item.
419426 Vector<int, UNISCRIBE_HELPER_STACK_RUNS> m_screenOrder;
 427
 428 // This contains Uniscribe's OpenType feature settings. This structure
 429 // is filled by using WebKit's |FontFeatureSettings|.
 430 TEXTRANGE_PROPERTIES m_rangeProperties;
 431 Vector<OPENTYPE_FEATURE_RECORD, UNISCRIBE_HELPER_FEATURES> m_featureRecords;
420432};
421433
422434} // namespace WebCore

Source/WebCore/platform/graphics/chromium/UniscribeHelperTextRun.cpp

@@UniscribeHelperTextRun::UniscribeHelperTextRun(const TextRun& run,
5353 setSpaceWidth(font.spaceWidth());
5454 setWordSpacing(font.wordSpacing());
5555 setAscent(font.fontMetrics().ascent());
 56 setRangeProperties(font.fontDescription().featureSettings());
5657
5758 init();
5859