WebCore:
authormitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Dec 2007 19:36:12 +0000 (19:36 +0000)
committermitz@apple.com <mitz@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 11 Dec 2007 19:36:12 +0000 (19:36 +0000)
        Reviewed by Darin Adler.

        - fix <rdar://problem/5631507> Text doesn't wrap properly at Tamil version of Wikipedia

        Test: fast/text/international/complex-character-based-fallback.html

        * platform/graphics/Font.cpp:
        (WebCore::Font::glyphDataForCharacter): Added a forceSmallCaps argument
        that forces this function to use the small caps font. It is used for
        combining marks that need to combine with a small cap.
        * platform/graphics/Font.h:
        * platform/win/UniscribeController.cpp:
        (WebCore::UniscribeController::advance): Changed to split the string
        into runs of characters that will be rendered using the same FontData.
        This is done by calling glyphDataForCharacter() for each cahracter to
        find the FontData it should be rendered with.
        (WebCore::UniscribeController::itemizeShapeAndPlace): Added a fontData
        argument that is passed on to shapeAndPlaceItem() instead of the
        smallCaps argument.
        (WebCore::UniscribeController::shapeAndPlaceItem): Added a fontData
        argument and removed the font fallback logic from this function, as
        it is now expected to be called with an item all of whose characters
        can be rendered with the given fontData.
        * platform/win/UniscribeController.h:

LayoutTests:

        Reviewed by Darin Adler.

        - test for <rdar://problem/5631507> Text doesn't wrap properly at Tamil version of Wikipedia

        * fast/text/international/complex-character-based-fallback.html: Added.
        * platform/mac-leopard/fast/text/international/complex-character-based-fallback-expected.checksum: Added.
        * platform/mac-leopard/fast/text/international/complex-character-based-fallback-expected.png: Added.
        * platform/mac/fast/text/international/complex-character-based-fallback-expected.txt: Added.
        * platform/win/fast/text: Added.
        * platform/win/fast/text/international: Added.
        * platform/win/fast/text/international/complex-character-based-fallback-expected.checksum: Added.
        * platform/win/fast/text/international/complex-character-based-fallback-expected.png: Added.
        * platform/win/fast/text/international/complex-character-based-fallback-expected.txt: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@28621 268f45cc-cd09-0410-ab3c-d52691b4dbfc

13 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/text/international/complex-character-based-fallback.html [new file with mode: 0644]
LayoutTests/platform/mac-leopard/fast/text/international/complex-character-based-fallback-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac-leopard/fast/text/international/complex-character-based-fallback-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/text/international/complex-character-based-fallback-expected.txt [new file with mode: 0644]
LayoutTests/platform/win/fast/text/international/complex-character-based-fallback-expected.checksum [new file with mode: 0644]
LayoutTests/platform/win/fast/text/international/complex-character-based-fallback-expected.png [new file with mode: 0644]
LayoutTests/platform/win/fast/text/international/complex-character-based-fallback-expected.txt [new file with mode: 0644]
WebCore/ChangeLog
WebCore/platform/graphics/Font.cpp
WebCore/platform/graphics/Font.h
WebCore/platform/win/UniscribeController.cpp
WebCore/platform/win/UniscribeController.h

index 603d80f2fa054568692dbf858f26758ab578972d..7aa4a8c93d8a3cc0906d8a721561dbad3fc02d35 100644 (file)
@@ -1,3 +1,19 @@
+2007-12-11  Dan Bernstein  <mitz@apple.com>
+
+        Reviewed by Darin Adler.
+
+        - test for <rdar://problem/5631507> Text doesn't wrap properly at Tamil version of Wikipedia
+
+        * fast/text/international/complex-character-based-fallback.html: Added.
+        * platform/mac-leopard/fast/text/international/complex-character-based-fallback-expected.checksum: Added.
+        * platform/mac-leopard/fast/text/international/complex-character-based-fallback-expected.png: Added.
+        * platform/mac/fast/text/international/complex-character-based-fallback-expected.txt: Added.
+        * platform/win/fast/text: Added.
+        * platform/win/fast/text/international: Added.
+        * platform/win/fast/text/international/complex-character-based-fallback-expected.checksum: Added.
+        * platform/win/fast/text/international/complex-character-based-fallback-expected.png: Added.
+        * platform/win/fast/text/international/complex-character-based-fallback-expected.txt: Added.
+
 2007-12-07  Alexey Proskuryakov  <ap@webkit.org>
 
         Reviewed by Darin.
diff --git a/LayoutTests/fast/text/international/complex-character-based-fallback.html b/LayoutTests/fast/text/international/complex-character-based-fallback.html
new file mode 100644 (file)
index 0000000..4ee74b3
Binary files /dev/null and b/LayoutTests/fast/text/international/complex-character-based-fallback.html differ
diff --git a/LayoutTests/platform/mac-leopard/fast/text/international/complex-character-based-fallback-expected.checksum b/LayoutTests/platform/mac-leopard/fast/text/international/complex-character-based-fallback-expected.checksum
new file mode 100644 (file)
index 0000000..2bbfb9f
--- /dev/null
@@ -0,0 +1 @@
+c82a724bccc52e6dedf03f0c9feb8876
\ No newline at end of file
diff --git a/LayoutTests/platform/mac-leopard/fast/text/international/complex-character-based-fallback-expected.png b/LayoutTests/platform/mac-leopard/fast/text/international/complex-character-based-fallback-expected.png
new file mode 100644 (file)
index 0000000..5d1c11c
Binary files /dev/null and b/LayoutTests/platform/mac-leopard/fast/text/international/complex-character-based-fallback-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/text/international/complex-character-based-fallback-expected.txt b/LayoutTests/platform/mac/fast/text/international/complex-character-based-fallback-expected.txt
new file mode 100644 (file)
index 0000000..45bb23b
--- /dev/null
@@ -0,0 +1,36 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x576
+      RenderBlock {P} at (0,0) size 784x36
+        RenderText {#text} at (0,0) size 780x36
+          text run at (0,0) width 780: "This tests that complex text that requires font fallback wraps correctly. The text is Tamil, which is not covered by the default"
+          text run at (0,18) width 421: "font, so fallback occurs. Note that the exclamation point in the end "
+        RenderInline {I} at (0,0) size 10x18
+          RenderText {#text} at (421,18) size 10x18
+            text run at (421,18) width 10: "is"
+        RenderText {#text} at (431,18) size 327x18
+          text run at (431,18) width 327: " covered by the default font and is rendered using it."
+      RenderBlock {P} at (0,52) size 306x132 [border: (3px solid #000000)]
+        RenderText {#text} at (3,3) size 285x126
+          text run at (3,3) width 159: "\x{B87}\x{BA4}\x{BC1} \x{B89}\x{B99}\x{BCD}\x{B95}\x{BB3}\x{BC8}\x{BAA}\x{BCD} \x{BAA}\x{BCB}\x{BA9}\x{BCD}\x{BB1}"
+          text run at (3,21) width 255: "\x{B86}\x{BB0}\x{BCD}\x{BB5}\x{BAE}\x{BC1}\x{B9F}\x{BC8}\x{BAF}\x{BB5}\x{BB0}\x{BCD}\x{B95}\x{BB3}\x{BBE}\x{BB2}\x{BCD} \x{BA4}\x{BCA}\x{B95}\x{BC1}\x{B95}\x{BCD}\x{B95}\x{BAA}\x{BCD}\x{BAA}\x{B9F}\x{BCD}\x{B9F}\x{BC1}"
+          text run at (3,39) width 267: "\x{B95}\x{B9F}\x{BCD}\x{B9F}\x{BC1}\x{BAA}\x{BCD}\x{BAA}\x{BBE}\x{B9F}\x{BC1}\x{B95}\x{BB3}\x{BCD} \x{B8F}\x{BA4}\x{BC1}\x{BAE}\x{BCD} \x{B87}\x{BA9}\x{BCD}\x{BB1}\x{BBF} \x{B87}\x{BB2}\x{BB5}\x{B9A}\x{BAE}\x{BBE}\x{B95}\x{BAA}\x{BCD}"
+          text run at (3,57) width 285: "\x{BAA}\x{BAF}\x{BA9}\x{BCD}\x{BAA}\x{B9F}\x{BC1}\x{BA4}\x{BCD}\x{BA4}\x{B95}\x{BCD}\x{B95}\x{BC2}\x{B9F}\x{BBF}\x{BAF} \x{B92}\x{BB0}\x{BC1} \x{BAA}\x{BA9}\x{BCD}\x{BAE}\x{BCA}\x{BB4}\x{BBF}\x{B95}\x{BCD} \x{B95}\x{BB2}\x{BC8}\x{B95}\x{BCD}"
+          text run at (3,75) width 264: "\x{B95}\x{BB3}\x{B9E}\x{BCD}\x{B9A}\x{BBF}\x{BAF}\x{BA4}\x{BCD} \x{BA4}\x{BBF}\x{B9F}\x{BCD}\x{B9F}\x{BAE}\x{BBE}\x{B95}\x{BC1}\x{BAE}\x{BCD}. \x{B87}\x{B99}\x{BCD}\x{B95}\x{BC1} \x{BA8}\x{BC0}\x{B99}\x{BCD}\x{B95}\x{BB3}\x{BC1}\x{BAE}\x{BCD}"
+          text run at (3,93) width 253: "\x{B89}\x{B99}\x{BCD}\x{B95}\x{BB3}\x{BC1}\x{B95}\x{BCD}\x{B95}\x{BC1} \x{BB5}\x{BBF}\x{BB0}\x{BC1}\x{BAA}\x{BCD}\x{BAA}\x{BAE}\x{BBE}\x{BA9} \x{BA4}\x{BB2}\x{BC8}\x{BAA}\x{BCD}\x{BAA}\x{BC1}\x{B95}\x{BB3}\x{BBF}\x{BB2}\x{BCD}"
+          text run at (3,111) width 149: "\x{BAA}\x{BC1}\x{BA4}\x{BBF}\x{BA4}\x{BBE}\x{B95}\x{B95}\x{BCD} \x{B95}\x{B9F}\x{BCD}\x{B9F}\x{BC1}\x{BB0}\x{BC8}\x{B95}\x{BB3}\x{BCD}!"
+      RenderBlock {P} at (0,200) size 784x36
+        RenderText {#text} at (0,0) size 778x36
+          text run at (0,0) width 778: "This is the same text but specifying a font that covers Tamil. Note that the exclamation point is rendered using the same font"
+          text run at (0,18) width 67: "as the text."
+      RenderBlock {P} at (0,252) size 306x132 [border: (3px solid #000000)]
+        RenderText {#text} at (3,3) size 285x126
+          text run at (3,3) width 159: "\x{B87}\x{BA4}\x{BC1} \x{B89}\x{B99}\x{BCD}\x{B95}\x{BB3}\x{BC8}\x{BAA}\x{BCD} \x{BAA}\x{BCB}\x{BA9}\x{BCD}\x{BB1}"
+          text run at (3,21) width 255: "\x{B86}\x{BB0}\x{BCD}\x{BB5}\x{BAE}\x{BC1}\x{B9F}\x{BC8}\x{BAF}\x{BB5}\x{BB0}\x{BCD}\x{B95}\x{BB3}\x{BBE}\x{BB2}\x{BCD} \x{BA4}\x{BCA}\x{B95}\x{BC1}\x{B95}\x{BCD}\x{B95}\x{BAA}\x{BCD}\x{BAA}\x{B9F}\x{BCD}\x{B9F}\x{BC1}"
+          text run at (3,39) width 267: "\x{B95}\x{B9F}\x{BCD}\x{B9F}\x{BC1}\x{BAA}\x{BCD}\x{BAA}\x{BBE}\x{B9F}\x{BC1}\x{B95}\x{BB3}\x{BCD} \x{B8F}\x{BA4}\x{BC1}\x{BAE}\x{BCD} \x{B87}\x{BA9}\x{BCD}\x{BB1}\x{BBF} \x{B87}\x{BB2}\x{BB5}\x{B9A}\x{BAE}\x{BBE}\x{B95}\x{BAA}\x{BCD}"
+          text run at (3,57) width 285: "\x{BAA}\x{BAF}\x{BA9}\x{BCD}\x{BAA}\x{B9F}\x{BC1}\x{BA4}\x{BCD}\x{BA4}\x{B95}\x{BCD}\x{B95}\x{BC2}\x{B9F}\x{BBF}\x{BAF} \x{B92}\x{BB0}\x{BC1} \x{BAA}\x{BA9}\x{BCD}\x{BAE}\x{BCA}\x{BB4}\x{BBF}\x{B95}\x{BCD} \x{B95}\x{BB2}\x{BC8}\x{B95}\x{BCD}"
+          text run at (3,75) width 264: "\x{B95}\x{BB3}\x{B9E}\x{BCD}\x{B9A}\x{BBF}\x{BAF}\x{BA4}\x{BCD} \x{BA4}\x{BBF}\x{B9F}\x{BCD}\x{B9F}\x{BAE}\x{BBE}\x{B95}\x{BC1}\x{BAE}\x{BCD}. \x{B87}\x{B99}\x{BCD}\x{B95}\x{BC1} \x{BA8}\x{BC0}\x{B99}\x{BCD}\x{B95}\x{BB3}\x{BC1}\x{BAE}\x{BCD}"
+          text run at (3,93) width 253: "\x{B89}\x{B99}\x{BCD}\x{B95}\x{BB3}\x{BC1}\x{B95}\x{BCD}\x{B95}\x{BC1} \x{BB5}\x{BBF}\x{BB0}\x{BC1}\x{BAA}\x{BCD}\x{BAA}\x{BAE}\x{BBE}\x{BA9} \x{BA4}\x{BB2}\x{BC8}\x{BAA}\x{BCD}\x{BAA}\x{BC1}\x{B95}\x{BB3}\x{BBF}\x{BB2}\x{BCD}"
+          text run at (3,111) width 149: "\x{BAA}\x{BC1}\x{BA4}\x{BBF}\x{BA4}\x{BBE}\x{B95}\x{B95}\x{BCD} \x{B95}\x{B9F}\x{BCD}\x{B9F}\x{BC1}\x{BB0}\x{BC8}\x{B95}\x{BB3}\x{BCD}!"
diff --git a/LayoutTests/platform/win/fast/text/international/complex-character-based-fallback-expected.checksum b/LayoutTests/platform/win/fast/text/international/complex-character-based-fallback-expected.checksum
new file mode 100644 (file)
index 0000000..3a35914
--- /dev/null
@@ -0,0 +1 @@
+c729f453d98b9c42e954330ce984e837
\ No newline at end of file
diff --git a/LayoutTests/platform/win/fast/text/international/complex-character-based-fallback-expected.png b/LayoutTests/platform/win/fast/text/international/complex-character-based-fallback-expected.png
new file mode 100644 (file)
index 0000000..9af8437
Binary files /dev/null and b/LayoutTests/platform/win/fast/text/international/complex-character-based-fallback-expected.png differ
diff --git a/LayoutTests/platform/win/fast/text/international/complex-character-based-fallback-expected.txt b/LayoutTests/platform/win/fast/text/international/complex-character-based-fallback-expected.txt
new file mode 100644 (file)
index 0000000..a93e723
--- /dev/null
@@ -0,0 +1,43 @@
+layer at (0,0) size 785x624
+  RenderView at (0,0) size 785x600
+layer at (0,0) size 785x624
+  RenderBlock {HTML} at (0,0) size 785x624
+    RenderBody {BODY} at (8,8) size 769x600
+      RenderBlock {P} at (0,0) size 769x54
+        RenderText {#text} at (0,0) size 733x36
+          text run at (0,0) width 733: "This tests that complex text that requires font fallback wraps correctly. The text is Tamil, which is not covered by the"
+          text run at (0,18) width 468: "default font, so fallback occurs. Note that the exclamation point in the end "
+        RenderInline {I} at (0,0) size 10x18
+          RenderText {#text} at (468,18) size 10x18
+            text run at (468,18) width 10: "is"
+        RenderText {#text} at (478,18) size 751x36
+          text run at (478,18) width 273: " covered by the default font and is rendered"
+          text run at (0,36) width 50: "using it."
+      RenderBlock {P} at (0,70) size 306x186 [border: (3px solid #000000)]
+        RenderText {#text} at (3,3) size 265x180
+          text run at (3,3) width 206: "\x{B87}\x{BA4}\x{BC1} \x{B89}\x{B99}\x{BCD}\x{B95}\x{BB3}\x{BC8}\x{BAA}\x{BCD} \x{BAA}\x{BCB}\x{BA9}\x{BCD}\x{BB1}"
+          text run at (3,21) width 209: "\x{B86}\x{BB0}\x{BCD}\x{BB5}\x{BAE}\x{BC1}\x{B9F}\x{BC8}\x{BAF}\x{BB5}\x{BB0}\x{BCD}\x{B95}\x{BB3}\x{BBE}\x{BB2}\x{BCD}"
+          text run at (3,39) width 265: "\x{BA4}\x{BCA}\x{B95}\x{BC1}\x{B95}\x{BCD}\x{B95}\x{BAA}\x{BCD}\x{BAA}\x{B9F}\x{BCD}\x{B9F}\x{BC1} \x{B95}\x{B9F}\x{BCD}\x{B9F}\x{BC1}\x{BAA}\x{BCD}\x{BAA}\x{BBE}\x{B9F}\x{BC1}\x{B95}\x{BB3}\x{BCD}"
+          text run at (3,57) width 222: "\x{B8F}\x{BA4}\x{BC1}\x{BAE}\x{BCD} \x{B87}\x{BA9}\x{BCD}\x{BB1}\x{BBF} \x{B87}\x{BB2}\x{BB5}\x{B9A}\x{BAE}\x{BBE}\x{B95}\x{BAA}\x{BCD}"
+          text run at (3,75) width 208: "\x{BAA}\x{BAF}\x{BA9}\x{BCD}\x{BAA}\x{B9F}\x{BC1}\x{BA4}\x{BCD}\x{BA4}\x{B95}\x{BCD}\x{B95}\x{BC2}\x{B9F}\x{BBF}\x{BAF} \x{B92}\x{BB0}\x{BC1}"
+          text run at (3,93) width 263: "\x{BAA}\x{BA9}\x{BCD}\x{BAE}\x{BCA}\x{BB4}\x{BBF}\x{B95}\x{BCD} \x{B95}\x{BB2}\x{BC8}\x{B95}\x{BCD} \x{B95}\x{BB3}\x{B9E}\x{BCD}\x{B9A}\x{BBF}\x{BAF}\x{BA4}\x{BCD}"
+          text run at (3,111) width 246: "\x{BA4}\x{BBF}\x{B9F}\x{BCD}\x{B9F}\x{BAE}\x{BBE}\x{B95}\x{BC1}\x{BAE}\x{BCD}. \x{B87}\x{B99}\x{BCD}\x{B95}\x{BC1} \x{BA8}\x{BC0}\x{B99}\x{BCD}\x{B95}\x{BB3}\x{BC1}\x{BAE}\x{BCD}"
+          text run at (3,129) width 213: "\x{B89}\x{B99}\x{BCD}\x{B95}\x{BB3}\x{BC1}\x{B95}\x{BCD}\x{B95}\x{BC1} \x{BB5}\x{BBF}\x{BB0}\x{BC1}\x{BAA}\x{BCD}\x{BAA}\x{BAE}\x{BBE}\x{BA9}"
+          text run at (3,147) width 207: "\x{BA4}\x{BB2}\x{BC8}\x{BAA}\x{BCD}\x{BAA}\x{BC1}\x{B95}\x{BB3}\x{BBF}\x{BB2}\x{BCD} \x{BAA}\x{BC1}\x{BA4}\x{BBF}\x{BA4}\x{BBE}\x{B95}\x{B95}\x{BCD}"
+          text run at (3,165) width 109: "\x{B95}\x{B9F}\x{BCD}\x{B9F}\x{BC1}\x{BB0}\x{BC8}\x{B95}\x{BB3}\x{BCD}!"
+      RenderBlock {P} at (0,272) size 769x36
+        RenderText {#text} at (0,0) size 749x36
+          text run at (0,0) width 749: "This is the same text but specifying a font that covers Tamil. Note that the exclamation point is rendered using the same"
+          text run at (0,18) width 96: "font as the text."
+      RenderBlock {P} at (0,324) size 306x276 [border: (3px solid #000000)]
+        RenderText {#text} at (3,3) size 273x270
+          text run at (3,3) width 216: "\x{B87}\x{BA4}\x{BC1} \x{B89}\x{B99}\x{BCD}\x{B95}\x{BB3}\x{BC8}\x{BAA}\x{BCD} \x{BAA}\x{BCB}\x{BA9}\x{BCD}\x{BB1}"
+          text run at (3,30) width 209: "\x{B86}\x{BB0}\x{BCD}\x{BB5}\x{BAE}\x{BC1}\x{B9F}\x{BC8}\x{BAF}\x{BB5}\x{BB0}\x{BCD}\x{B95}\x{BB3}\x{BBE}\x{BB2}\x{BCD}"
+          text run at (3,57) width 270: "\x{BA4}\x{BCA}\x{B95}\x{BC1}\x{B95}\x{BCD}\x{B95}\x{BAA}\x{BCD}\x{BAA}\x{B9F}\x{BCD}\x{B9F}\x{BC1} \x{B95}\x{B9F}\x{BCD}\x{B9F}\x{BC1}\x{BAA}\x{BCD}\x{BAA}\x{BBE}\x{B9F}\x{BC1}\x{B95}\x{BB3}\x{BCD}"
+          text run at (3,84) width 232: "\x{B8F}\x{BA4}\x{BC1}\x{BAE}\x{BCD} \x{B87}\x{BA9}\x{BCD}\x{BB1}\x{BBF} \x{B87}\x{BB2}\x{BB5}\x{B9A}\x{BAE}\x{BBE}\x{B95}\x{BAA}\x{BCD}"
+          text run at (3,111) width 213: "\x{BAA}\x{BAF}\x{BA9}\x{BCD}\x{BAA}\x{B9F}\x{BC1}\x{BA4}\x{BCD}\x{BA4}\x{B95}\x{BCD}\x{B95}\x{BC2}\x{B9F}\x{BBF}\x{BAF} \x{B92}\x{BB0}\x{BC1}"
+          text run at (3,138) width 273: "\x{BAA}\x{BA9}\x{BCD}\x{BAE}\x{BCA}\x{BB4}\x{BBF}\x{B95}\x{BCD} \x{B95}\x{BB2}\x{BC8}\x{B95}\x{BCD} \x{B95}\x{BB3}\x{B9E}\x{BCD}\x{B9A}\x{BBF}\x{BAF}\x{BA4}\x{BCD}"
+          text run at (3,165) width 256: "\x{BA4}\x{BBF}\x{B9F}\x{BCD}\x{B9F}\x{BAE}\x{BBE}\x{B95}\x{BC1}\x{BAE}\x{BCD}. \x{B87}\x{B99}\x{BCD}\x{B95}\x{BC1} \x{BA8}\x{BC0}\x{B99}\x{BCD}\x{B95}\x{BB3}\x{BC1}\x{BAE}\x{BCD}"
+          text run at (3,192) width 218: "\x{B89}\x{B99}\x{BCD}\x{B95}\x{BB3}\x{BC1}\x{B95}\x{BCD}\x{B95}\x{BC1} \x{BB5}\x{BBF}\x{BB0}\x{BC1}\x{BAA}\x{BCD}\x{BAA}\x{BAE}\x{BBE}\x{BA9}"
+          text run at (3,219) width 212: "\x{BA4}\x{BB2}\x{BC8}\x{BAA}\x{BCD}\x{BAA}\x{BC1}\x{B95}\x{BB3}\x{BBF}\x{BB2}\x{BCD} \x{BAA}\x{BC1}\x{BA4}\x{BBF}\x{BA4}\x{BBE}\x{B95}\x{B95}\x{BCD}"
+          text run at (3,246) width 109: "\x{B95}\x{B9F}\x{BCD}\x{B9F}\x{BC1}\x{BB0}\x{BC8}\x{B95}\x{BB3}\x{BCD}!"
index a116cc7167050bb28ed44e11edb98c8fa1563869..0ad81d2c76f96acf42cabec9e4084314f4885a90 100644 (file)
@@ -1,3 +1,30 @@
+2007-12-11  Dan Bernstein  <mitz@apple.com>
+
+        Reviewed by Darin Adler.
+
+        - fix <rdar://problem/5631507> Text doesn't wrap properly at Tamil version of Wikipedia
+
+        Test: fast/text/international/complex-character-based-fallback.html
+
+        * platform/graphics/Font.cpp:
+        (WebCore::Font::glyphDataForCharacter): Added a forceSmallCaps argument
+        that forces this function to use the small caps font. It is used for
+        combining marks that need to combine with a small cap.
+        * platform/graphics/Font.h:
+        * platform/win/UniscribeController.cpp:
+        (WebCore::UniscribeController::advance): Changed to split the string
+        into runs of characters that will be rendered using the same FontData.
+        This is done by calling glyphDataForCharacter() for each cahracter to
+        find the FontData it should be rendered with.
+        (WebCore::UniscribeController::itemizeShapeAndPlace): Added a fontData
+        argument that is passed on to shapeAndPlaceItem() instead of the
+        smallCaps argument.
+        (WebCore::UniscribeController::shapeAndPlaceItem): Added a fontData
+        argument and removed the font fallback logic from this function, as
+        it is now expected to be called with an item all of whose characters
+        can be rendered with the given fontData.
+        * platform/win/UniscribeController.h:
+
 2007-12-07  Alexey Proskuryakov  <ap@webkit.org>
 
         Reviewed by Darin.
index 48864cbeca35dbec86ebe8e2eb30a68d5a0b296b..93ee4b9590fbb4e3f0c979dfb90a39c52c2fb28e 100644 (file)
@@ -344,14 +344,10 @@ bool Font::operator==(const Font& other) const
            && m_letterSpacing == other.m_letterSpacing
            && m_wordSpacing == other.m_wordSpacing;
 }
-    
-// FIXME: It is unfortunate that this function needs to be passed the original cluster.
-// It is only required for the platform's FontCache::getFontDataForCharacters(), and it means
-// that this function is not correct if it transforms the character to uppercase and calls
-// FontCache::getFontDataForCharacters() afterwards.
-const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror) const
+
+const GlyphData& Font::glyphDataForCharacter(UChar32 c, bool mirror, bool forceSmallCaps) const
 {
-    bool useSmallCapsFont = false;
+    bool useSmallCapsFont = forceSmallCaps;
     if (m_fontDescription.smallCaps()) {
         UChar32 upperC = Unicode::toUpper(c);
         if (upperC != c) {
index af703dccfc9d06577c7376f5774734f35125b2ac..277dadd72f2208662c97a930c0aedc8b6bd9399d 100644 (file)
@@ -189,7 +189,7 @@ public:
 #if !PLATFORM(QT)
     const FontData* primaryFont() const;
     const FontData* fontDataAt(unsigned) const;
-    const GlyphData& glyphDataForCharacter(UChar32, bool mirror) const;
+    const GlyphData& glyphDataForCharacter(UChar32, bool mirror, bool forceSmallCaps = false) const;
     // Used for complex text, and does not utilize the glyph map cache.
     const FontData* fontDataForCharacters(const UChar*, int length) const;
 
index 73158510c56ba67002d00a0e354e4a467f496d75..41c19eb71506a8c4a4c1050e6c271b9effd28492 100644 (file)
@@ -101,52 +101,66 @@ void UniscribeController::advance(unsigned offset, GlyphBuffer* glyphBuffer)
     if (length <= 0)
         return;
 
-    // We break up itemization of the string if small caps is involved.
-    // Adjust the characters to account for small caps if it is set.
-    if (m_font.isSmallCaps()) {
-        // FIXME: It's inconsistent that we use logical order when itemizing, since this
-        // does not match normal RTL.
-        Vector<UChar> smallCapsBuffer(length);
-        memcpy(smallCapsBuffer.data(), cp, length * sizeof(UChar));
-        bool isSmallCaps = false;
-        unsigned indexOfCaseShift = m_run.rtl() ? length - 1 : 0;
-        const UChar* curr = m_run.rtl() ? cp + length  - 1: cp;
-        const UChar* end = m_run.rtl() ? cp - 1: cp + length;
-        while (curr != end) {
-            int index = curr - cp;
-            UChar c = smallCapsBuffer[index];
-            UChar newC;
-            curr = m_run.rtl() ? curr - 1 : curr + 1;
-            if (U_GET_GC_MASK(c) & U_GC_M_MASK)
-                continue;
-            if (!u_isUUppercase(c) && (newC = u_toupper(c)) != c) {
-                smallCapsBuffer[index] = newC;
-                if (!isSmallCaps) {
-                    isSmallCaps = true;
-                    int itemStart = m_run.rtl() ? index : indexOfCaseShift;
-                    int itemLength = m_run.rtl() ? indexOfCaseShift - index : index - indexOfCaseShift;
-                    itemizeShapeAndPlace(smallCapsBuffer.data() + itemStart, itemLength, false, glyphBuffer);
-                    indexOfCaseShift = index;
-                }
-            } else if (isSmallCaps) {
-                isSmallCaps = false;
-                int itemStart = m_run.rtl() ? index : indexOfCaseShift;
-                int itemLength = m_run.rtl() ? indexOfCaseShift - index : index - indexOfCaseShift;
-                itemizeShapeAndPlace(smallCapsBuffer.data() + itemStart, itemLength, true, glyphBuffer);
-                indexOfCaseShift = index;
-            }
+    // We break up itemization of the string by fontData and (if needed) the use of small caps.
+
+    // FIXME: It's inconsistent that we use logical order when itemizing, since this
+    // does not match normal RTL.
+
+    // FIXME: This function should decode surrogate pairs. Currently it makes little difference that
+    // it does not because the font cache on Windows does not support non-BMP characters.
+    Vector<UChar, 256> smallCapsBuffer;
+    if (m_font.isSmallCaps())
+        smallCapsBuffer.resize(length);
+
+    unsigned indexOfFontTransition = m_run.rtl() ? length - 1 : 0;
+    const UChar* curr = m_run.rtl() ? cp + length  - 1 : cp;
+    const UChar* end = m_run.rtl() ? cp - 1 : cp + length;
+
+    const FontData* fontData;
+    const FontData* nextFontData = m_font.glyphDataForCharacter(*curr, false).fontData;
+
+    UChar newC;
+
+    bool isSmallCaps;
+    bool nextIsSmallCaps = m_font.isSmallCaps() && !(U_GET_GC_MASK(*curr) & U_GC_M_MASK) && (newC = u_toupper(*curr)) != *curr;
+
+    if (nextIsSmallCaps)
+        smallCapsBuffer[curr - cp] = newC;
+
+    while (true) {
+        curr = m_run.rtl() ? curr - 1 : curr + 1;
+        if (curr == end)
+            break;
+
+        fontData = nextFontData;
+        isSmallCaps = nextIsSmallCaps;
+        int index = curr - cp;
+        UChar c = *curr;
+
+        bool forceSmallCaps = isSmallCaps && (U_GET_GC_MASK(c) & U_GC_M_MASK);
+        nextFontData = m_font.glyphDataForCharacter(*curr, false, forceSmallCaps).fontData;
+        if (m_font.isSmallCaps()) {
+            nextIsSmallCaps = forceSmallCaps || (newC = u_toupper(c)) != c;
+            if (nextIsSmallCaps)
+                smallCapsBuffer[index] = forceSmallCaps ? c : newC;
         }
-        
-        int itemLength = m_run.rtl() ? indexOfCaseShift + 1 : length - indexOfCaseShift;
-        if (itemLength) {
-            int itemStart = m_run.rtl() ? 0 : indexOfCaseShift;
-            itemizeShapeAndPlace(smallCapsBuffer.data() + itemStart, itemLength, isSmallCaps, glyphBuffer);
+
+        if (nextFontData != fontData || nextIsSmallCaps != isSmallCaps) {
+            int itemStart = m_run.rtl() ? index : indexOfFontTransition;
+            int itemLength = m_run.rtl() ? indexOfFontTransition - index : index - indexOfFontTransition;
+            itemizeShapeAndPlace((isSmallCaps ? smallCapsBuffer.data() : cp) + itemStart, itemLength, fontData, glyphBuffer);
+            indexOfFontTransition = index;
         }
-    } else
-        itemizeShapeAndPlace(cp, length, false, glyphBuffer);
+    }
+    
+    int itemLength = m_run.rtl() ? indexOfFontTransition + 1 : length - indexOfFontTransition;
+    if (itemLength) {
+        int itemStart = m_run.rtl() ? 0 : indexOfFontTransition;
+        itemizeShapeAndPlace((nextIsSmallCaps ? smallCapsBuffer.data() : cp) + itemStart, itemLength, nextFontData, glyphBuffer);
+    }
 }
 
-void UniscribeController::itemizeShapeAndPlace(const UChar* cp, unsigned length, bool smallCaps, GlyphBuffer* glyphBuffer)
+void UniscribeController::itemizeShapeAndPlace(const UChar* cp, unsigned length, const FontData* fontData, GlyphBuffer* glyphBuffer)
 {
     // ScriptItemize (in Windows XP versions prior to SP2) can overflow by 1.  This is why there is an extra empty item
     // hanging out at the end of the array
@@ -160,12 +174,12 @@ void UniscribeController::itemizeShapeAndPlace(const UChar* cp, unsigned length,
 
     if (m_run.rtl()) {
         for (int i = m_items.size() - 2; i >= 0; i--) {
-            if (!shapeAndPlaceItem(cp, i, smallCaps, glyphBuffer))
+            if (!shapeAndPlaceItem(cp, i, fontData, glyphBuffer))
                 return;
         }
     } else {
         for (unsigned i = 0; i < m_items.size() - 1; i++) {
-            if (!shapeAndPlaceItem(cp, i, smallCaps, glyphBuffer))
+            if (!shapeAndPlaceItem(cp, i, fontData, glyphBuffer))
                 return;
         }
     }
@@ -185,59 +199,26 @@ void UniscribeController::resetControlAndState()
     m_state.fOverrideDirection = m_run.directionalOverride();
 }
 
-bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, bool smallCaps, GlyphBuffer* glyphBuffer)
+bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, const FontData* fontData, GlyphBuffer* glyphBuffer)
 {
     // Determine the string for this item.
     const UChar* str = cp + m_items[i].iCharPos;
     int len = m_items[i+1].iCharPos - m_items[i].iCharPos;
     SCRIPT_ITEM item = m_items[i];
 
-    // Get our current FontData that we are using.
-    unsigned dataIndex = 0;
-    const FontData* fontData = m_font.fontDataAt(dataIndex);
-    if (smallCaps)
-        fontData = fontData->smallCapsFontData(m_font.fontDescription());
-
     // Set up buffers to hold the results of shaping the item.
     Vector<WORD> glyphs;
     Vector<WORD> clusters;
     Vector<SCRIPT_VISATTR> visualAttributes;
     clusters.resize(len);
      
-    // Shape the item.  This will provide us with glyphs for the item.  We will
-    // attempt to shape using the first available FontData.  If the shaping produces a result with missing
-    // glyphs, then we will fall back to the next FontData.
-    // FIXME: This isn't as good as per-glyph fallback, but in practice it should be pretty good, since
-    // items are broken up by "shaping engine", meaning unique scripts will be broken up into
-    // separate items.
-    bool lastResortFontTried = false;
-    while (fontData) {
-        // The recommended size for the glyph buffer is 1.5 * the character length + 16 in the uniscribe docs.
-        // Apparently this is a good size to avoid having to make repeated calls to ScriptShape.
-        glyphs.resize(1.5 * len + 16);
-        visualAttributes.resize(glyphs.size());
-   
-        if (shape(str, len, item, fontData, glyphs, clusters, visualAttributes))
-            break;
-        
-        // Try again with the next font in the list.
-        if (lastResortFontTried) {
-            fontData = 0;
-            break;
-        }
-        
-        fontData = m_font.fontDataAt(++dataIndex);
-        if (!fontData) {
-            // Out of fonts.  Get a font data based on the actual characters.
-            fontData = m_font.fontDataForCharacters(str, len);
-            lastResortFontTried = true;
-        }
-        if (smallCaps)
-            fontData = fontData->smallCapsFontData(m_font.fontDescription());
-    }
+    // Shape the item.
+    // The recommended size for the glyph buffer is 1.5 * the character length + 16 in the uniscribe docs.
+    // Apparently this is a good size to avoid having to make repeated calls to ScriptShape.
+    glyphs.resize(1.5 * len + 16);
+    visualAttributes.resize(glyphs.size());
 
-    // Just give up.  We were unable to shape.
-    if (!fontData)
+    if (!shape(str, len, item, fontData, glyphs, clusters, visualAttributes))
         return true;
 
     // We now have a collection of glyphs.
@@ -282,13 +263,13 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, bool sm
             // array.
             glyphs[clusters[k]] = fontData->m_spaceGlyph;
             advances[clusters[k]] = logicalSpaceWidth;
-            spaceCharacters[clusters[k]] = m_currentCharacter + k + m_items[i].iCharPos;
+            spaceCharacters[clusters[k]] = m_currentCharacter + k + item.iCharPos;
         }
 
         if (Font::isRoundingHackCharacter(ch))
-            roundingHackCharacters[clusters[k]] = m_currentCharacter + k + m_items[i].iCharPos;
+            roundingHackCharacters[clusters[k]] = m_currentCharacter + k + item.iCharPos;
 
-        int boundary = k + m_currentCharacter + m_items[i].iCharPos;
+        int boundary = k + m_currentCharacter + item.iCharPos;
         if (boundary < m_run.length() &&
             Font::isRoundingHackCharacter(*(str + k + 1)))
             roundingHackWordBoundaries[clusters[k]] = boundary;
@@ -344,7 +325,7 @@ bool UniscribeController::shapeAndPlaceItem(const UChar* cp, unsigned i, bool sm
 
                 // Account for word-spacing.
                 int characterIndex = spaceCharacters[k];
-                if (characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex-1)) && m_font.wordSpacing())
+                if (characterIndex > 0 && !Font::treatAsSpace(*m_run.data(characterIndex - 1)) && m_font.wordSpacing())
                     advance += m_font.wordSpacing();
             }
         }
index 4ba7325b99ad2a900e61fc818418fcae8b3833cc..1fe0439cde489f5020f9a2766a4110e84c3aeff9 100644 (file)
@@ -52,8 +52,8 @@ public:
 private:    
     void resetControlAndState();
 
-    void itemizeShapeAndPlace(const UChar*, unsigned length, bool smallCaps, GlyphBuffer* glyphBuffer);
-    bool shapeAndPlaceItem(const UChar*, unsigned index, bool smallCaps, GlyphBuffer*);
+    void itemizeShapeAndPlace(const UChar*, unsigned length, const FontData*, GlyphBuffer*);
+    bool shapeAndPlaceItem(const UChar*, unsigned index, const FontData*, GlyphBuffer*);
     bool shape(const UChar* str, int len, SCRIPT_ITEM item, const FontData* fontData,
                Vector<WORD>& glyphs, Vector<WORD>& clusters,
                Vector<SCRIPT_VISATTR>& visualAttributes);