summaryrefslogtreecommitdiffstats
path: root/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp')
-rw-r--r--Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp114
1 files changed, 68 insertions, 46 deletions
diff --git a/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
index dda84a9..524beec 100644
--- a/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
+++ b/Source/WebCore/platform/graphics/chromium/UniscribeHelper.cpp
@@ -31,45 +31,16 @@
#include "config.h"
#include "UniscribeHelper.h"
-#include <windows.h>
-
+#include "Font.h"
#include "FontUtilsChromiumWin.h"
#include "PlatformContextSkia.h"
#include "SkiaFontWin.h"
#include "SkPoint.h"
+#include <windows.h>
#include <wtf/Assertions.h>
namespace WebCore {
-// This function is used to see where word spacing should be applied inside
-// runs. Note that this must match Font::treatAsSpace so we all agree where
-// and how much space this is, so we don't want to do more general Unicode
-// "is this a word break" thing.
-static bool treatAsSpace(UChar c)
-{
- return c == ' ' || c == '\t' || c == '\n' || c == 0x00A0;
-}
-
-// SCRIPT_FONTPROPERTIES contains glyph indices for default, invalid
-// and blank glyphs. Just because ScriptShape succeeds does not mean
-// that a text run is rendered correctly. Some characters may be rendered
-// with default/invalid/blank glyphs. Therefore, we need to check if the glyph
-// array returned by ScriptShape contains any of those glyphs to make
-// sure that the text run is rendered successfully.
-static bool containsMissingGlyphs(WORD *glyphs,
- int length,
- SCRIPT_FONTPROPERTIES* properties)
-{
- for (int i = 0; i < length; ++i) {
- if (glyphs[i] == properties->wgDefault
- || (glyphs[i] == properties->wgInvalid
- && glyphs[i] != properties->wgBlank))
- return true;
- }
-
- return false;
-}
-
// HFONT is the 'incarnation' of 'everything' about font, but it's an opaque
// handle and we can't directly query it to make a new HFONT sharing
// its characteristics (height, style, etc) except for family name.
@@ -102,13 +73,15 @@ UniscribeHelper::UniscribeHelper(const UChar* input,
bool isRtl,
HFONT hfont,
SCRIPT_CACHE* scriptCache,
- SCRIPT_FONTPROPERTIES* fontProperties)
+ SCRIPT_FONTPROPERTIES* fontProperties,
+ WORD spaceGlyph)
: m_input(input)
, m_inputLength(inputLength)
, m_isRtl(isRtl)
, m_hfont(hfont)
, m_scriptCache(scriptCache)
, m_fontProperties(fontProperties)
+ , m_spaceGlyph(spaceGlyph)
, m_directionalOverride(false)
, m_inhibitLigate(false)
, m_letterSpacing(0)
@@ -546,6 +519,7 @@ bool UniscribeHelper::shape(const UChar* input,
SCRIPT_CACHE* scriptCache = m_scriptCache;
SCRIPT_FONTPROPERTIES* fontProperties = m_fontProperties;
int ascent = m_ascent;
+ WORD spaceGlyph = m_spaceGlyph;
HDC tempDC = 0;
HGDIOBJ oldFont = 0;
HRESULT hr;
@@ -601,7 +575,7 @@ bool UniscribeHelper::shape(const UChar* input,
} else if (hr == E_OUTOFMEMORY) {
numGlyphs *= 2;
continue;
- } else if (SUCCEEDED(hr) && (lastFallbackTried || !containsMissingGlyphs(&shaping.m_glyphs[0], generatedGlyphs, fontProperties)))
+ } else if (SUCCEEDED(hr) && (lastFallbackTried || !containsMissingGlyphs(shaping, run, fontProperties)))
break;
// The current font can't render this run. clear DC and try
@@ -632,7 +606,9 @@ bool UniscribeHelper::shape(const UChar* input,
const UChar *family = getFallbackFamily(input, itemLength,
FontDescription::StandardFamily, 0, 0);
bool fontOk = getDerivedFontData(family, m_style, &m_logfont,
- &ascent, &hfont, &scriptCache);
+ &ascent, &hfont, &scriptCache,
+ &spaceGlyph);
+
if (!fontOk) {
// If this GetDerivedFontData is called from the renderer it
@@ -644,7 +620,8 @@ bool UniscribeHelper::shape(const UChar* input,
// Try again.
fontOk = getDerivedFontData(family, m_style, &m_logfont,
- &ascent, &hfont, &scriptCache);
+ &ascent, &hfont, &scriptCache,
+ &spaceGlyph);
ASSERT(fontOk);
}
@@ -673,6 +650,7 @@ bool UniscribeHelper::shape(const UChar* input,
// because it's not used elsewhere.
shaping.m_hfont = hfont;
shaping.m_scriptCache = scriptCache;
+ shaping.m_spaceGlyph = spaceGlyph;
// The ascent of a font for this run can be different from
// that of the primary font so that we need to keep track of
@@ -806,22 +784,39 @@ void UniscribeHelper::adjustSpaceAdvances()
for (size_t run = 0; run < m_runs.size(); run++) {
Shaping& shaping = m_shapes[run];
+ // FIXME: This loop is not UTF-16-safe. Unicode 6.0 has a couple
+ // of complex script blocks in Plane 1.
for (int i = 0; i < shaping.charLength(); i++) {
- if (!treatAsSpace(m_input[m_runs[run].iCharPos + i]))
+ UChar c = m_input[m_runs[run].iCharPos + i];
+ bool treatAsSpace = Font::treatAsSpace(c);
+ if (!treatAsSpace && !Font::treatAsZeroWidthSpaceInComplexScript(c))
continue;
int glyphIndex = shaping.m_logs[i];
int currentAdvance = shaping.m_advance[glyphIndex];
- // currentAdvance does not include additional letter-spacing, but
- // space_width does. Here we find out how off we are from the
- // correct width for the space not including letter-spacing, then
- // just subtract that diff.
- int diff = currentAdvance - spaceWidthWithoutLetterSpacing;
- // The shaping can consist of a run of text, so only subtract the
- // difference in the width of the glyph.
- shaping.m_advance[glyphIndex] -= diff;
- shaping.m_abc.abcB -= diff;
+ if (treatAsSpace) {
+ // currentAdvance does not include additional letter-spacing,
+ // but m_spaceWidth does. Here we find out how off we are from
+ // the correct width (spaceWidthWithoutLetterSpacing) and
+ // just subtract that diff.
+ int diff = currentAdvance - spaceWidthWithoutLetterSpacing;
+ // The shaping can consist of a run of text, so only subtract
+ // the difference in the width of the glyph.
+ shaping.m_advance[glyphIndex] -= diff;
+ shaping.m_abc.abcB -= diff;
+ continue;
+ }
+
+ // For characters treated as zero-width space in complex
+ // scripts, set the advance width to zero, adjust
+ // |abcB| of the current run accordingly and set
+ // the glyph to m_spaceGlyph (invisible).
+ shaping.m_advance[glyphIndex] = 0;
+ shaping.m_abc.abcB -= currentAdvance;
+ shaping.m_offsets[glyphIndex].du = 0;
+ shaping.m_offsets[glyphIndex].dv = 0;
+ shaping.m_glyphs[glyphIndex] = shaping.m_spaceGlyph;
}
}
}
@@ -872,7 +867,7 @@ void UniscribeHelper::applySpacing()
// extra wordspacing amount for the glyphs they correspond to.
if (m_wordSpacing != 0) {
for (int i = 0; i < shaping.charLength(); i++) {
- if (!treatAsSpace(m_input[m_runs[run].iCharPos + i]))
+ if (!Font::treatAsSpace(m_input[m_runs[run].iCharPos + i]))
continue;
// The char in question is a word separator...
@@ -929,4 +924,31 @@ int UniscribeHelper::advanceForItem(int itemIndex) const
return shaping.m_prePadding + justification;
}
+// SCRIPT_FONTPROPERTIES contains glyph indices for default, invalid
+// and blank glyphs. Just because ScriptShape succeeds does not mean
+// that a text run is rendered correctly. Some characters may be rendered
+// with default/invalid/blank glyphs. Therefore, we need to check if the glyph
+// array returned by ScriptShape contains any of those glyphs to make
+// sure that the text run is rendered successfully.
+// However, we should not subject zero-width characters to this test.
+
+bool UniscribeHelper::containsMissingGlyphs(const Shaping& shaping,
+ const SCRIPT_ITEM& run,
+ const SCRIPT_FONTPROPERTIES* properties) const
+{
+ for (int i = 0; i < shaping.charLength(); i++) {
+ UChar c = m_input[run.iCharPos + i];
+ // Skip zero-width space characters because they're not considered to be missing in a font.
+ if (Font::treatAsZeroWidthSpaceInComplexScript(c))
+ continue;
+ int glyphIndex = shaping.m_logs[i];
+ WORD glyph = shaping.m_glyphs[glyphIndex];
+ if (glyph == properties->wgDefault
+ || (glyph == properties->wgInvalid && glyph != properties->wgBlank))
+ return true;
+ }
+ return false;
+}
+
+
} // namespace WebCore