Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(43)

Side by Side Diff: Source/core/html/canvas/CanvasRenderingContext2D.cpp

Issue 293653002: Canvas fillText and measureText handle ideographic spaces differently. (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: add v/g/* test expectations Created 6 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « LayoutTests/fast/canvas/canvas-text-space-characters.html ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies) 3 * Copyright (C) 2008, 2010 Nokia Corporation and/or its subsidiary(-ies)
4 * Copyright (C) 2007 Alp Toker <alp@atoker.com> 4 * Copyright (C) 2007 Alp Toker <alp@atoker.com>
5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org> 5 * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org> 6 * Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved. 7 * Copyright (C) 2010 Torch Mobile (Beijing) Co. Ltd. All rights reserved.
8 * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved. 8 * Copyright (C) 2012, 2013 Intel Corporation. All rights reserved.
9 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. 9 * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
10 * 10 *
(...skipping 2006 matching lines...) Expand 10 before | Expand all | Expand 10 after
2017 void CanvasRenderingContext2D::strokeText(const String& text, float x, float y) 2017 void CanvasRenderingContext2D::strokeText(const String& text, float x, float y)
2018 { 2018 {
2019 drawTextInternal(text, x, y, false); 2019 drawTextInternal(text, x, y, false);
2020 } 2020 }
2021 2021
2022 void CanvasRenderingContext2D::strokeText(const String& text, float x, float y, float maxWidth) 2022 void CanvasRenderingContext2D::strokeText(const String& text, float x, float y, float maxWidth)
2023 { 2023 {
2024 drawTextInternal(text, x, y, false, maxWidth, true); 2024 drawTextInternal(text, x, y, false, maxWidth, true);
2025 } 2025 }
2026 2026
2027 static inline bool isSpaceCharacter(UChar c)
2028 {
2029 // According to specification all space characters should be replaced with 0 x0020 space character.
2030 // http://www.whatwg.org/specs/web-apps/current-work/multipage/the-canvas-el ement.html#text-preparation-algorithm
2031 // The space characters according to specification are : U+0020, U+0009, U+0 00A, U+000C, and U+000D.
2032 // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-micros yntaxes.html#space-character
2033 // This function returns true for 0x000B also, so that this is backward comp atible.
2034 // Otherwise, the test LayoutTests/canvas/philip/tests/2d.text.draw.space.co llapse.space.html will fail
2035 return c == 0x0009 || c == 0x000A || c == 0x000B || c == 0x000C || c == 0x00 0D;
2036 }
2037
2038 static String normalizeSpaces(const String& text)
2039 {
2040 unsigned textLength = text.length();
2041 Vector<UChar> charVector(textLength);
2042
2043 for (unsigned i = 0; i < textLength; i++) {
2044 if (isSpaceCharacter(text[i]))
2045 charVector[i] = ' ';
2046 else
2047 charVector[i] = text[i];
2048 }
2049
2050 return String(charVector);
2051 }
2052
2027 PassRefPtr<TextMetrics> CanvasRenderingContext2D::measureText(const String& text ) 2053 PassRefPtr<TextMetrics> CanvasRenderingContext2D::measureText(const String& text )
2028 { 2054 {
2029 RefPtr<TextMetrics> metrics = TextMetrics::create(); 2055 RefPtr<TextMetrics> metrics = TextMetrics::create();
2030 2056
2031 // The style resolution required for rendering text is not available in fram e-less documents. 2057 // The style resolution required for rendering text is not available in fram e-less documents.
2032 if (!canvas()->document().frame()) 2058 if (!canvas()->document().frame())
2033 return metrics.release(); 2059 return metrics.release();
2034 2060
2035 FontCachePurgePreventer fontCachePurgePreventer; 2061 FontCachePurgePreventer fontCachePurgePreventer;
2036 canvas()->document().updateRenderTreeIfNeeded(); 2062 canvas()->document().updateRenderTreeIfNeeded();
2037 const Font& font = accessFont(); 2063 const Font& font = accessFont();
2038 const TextRun textRun(text); 2064 String normalizedText = normalizeSpaces(text);
2065 const TextRun textRun(normalizedText);
2039 FloatRect textBounds = font.selectionRectForText(textRun, FloatPoint(), font .fontDescription().computedSize(), 0, -1, true); 2066 FloatRect textBounds = font.selectionRectForText(textRun, FloatPoint(), font .fontDescription().computedSize(), 0, -1, true);
2040 2067
2041 // x direction 2068 // x direction
2042 metrics->setWidth(font.width(textRun)); 2069 metrics->setWidth(font.width(textRun));
2043 metrics->setActualBoundingBoxLeft(-textBounds.x()); 2070 metrics->setActualBoundingBoxLeft(-textBounds.x());
2044 metrics->setActualBoundingBoxRight(textBounds.maxX()); 2071 metrics->setActualBoundingBoxRight(textBounds.maxX());
2045 2072
2046 // y direction 2073 // y direction
2047 const FontMetrics& fontMetrics = font.fontMetrics(); 2074 const FontMetrics& fontMetrics = font.fontMetrics();
2048 const float ascent = fontMetrics.floatAscent(); 2075 const float ascent = fontMetrics.floatAscent();
2049 const float descent = fontMetrics.floatDescent(); 2076 const float descent = fontMetrics.floatDescent();
2050 const float baselineY = getFontBaseline(fontMetrics); 2077 const float baselineY = getFontBaseline(fontMetrics);
2051 2078
2052 metrics->setFontBoundingBoxAscent(ascent - baselineY); 2079 metrics->setFontBoundingBoxAscent(ascent - baselineY);
2053 metrics->setFontBoundingBoxDescent(descent + baselineY); 2080 metrics->setFontBoundingBoxDescent(descent + baselineY);
2054 metrics->setActualBoundingBoxAscent(-textBounds.y() - baselineY); 2081 metrics->setActualBoundingBoxAscent(-textBounds.y() - baselineY);
2055 metrics->setActualBoundingBoxDescent(textBounds.maxY() + baselineY); 2082 metrics->setActualBoundingBoxDescent(textBounds.maxY() + baselineY);
2056 2083
2057 // Note : top/bottom and ascend/descend are currently the same, so there's n o difference 2084 // Note : top/bottom and ascend/descend are currently the same, so there's n o difference
2058 // between the EM box's top and bottom and the font's ascend and desc end 2085 // between the EM box's top and bottom and the font's ascend and desc end
2059 metrics->setEmHeightAscent(0); 2086 metrics->setEmHeightAscent(0);
2060 metrics->setEmHeightDescent(0); 2087 metrics->setEmHeightDescent(0);
2061 2088
2062 metrics->setHangingBaseline(-0.8f * ascent + baselineY); 2089 metrics->setHangingBaseline(-0.8f * ascent + baselineY);
2063 metrics->setAlphabeticBaseline(baselineY); 2090 metrics->setAlphabeticBaseline(baselineY);
2064 metrics->setIdeographicBaseline(descent + baselineY); 2091 metrics->setIdeographicBaseline(descent + baselineY);
2065 return metrics.release(); 2092 return metrics.release();
2066 } 2093 }
2067 2094
2068 static void replaceCharacterInString(String& text, WTF::CharacterMatchFunctionPt r matchFunction, const String& replacement)
2069 {
2070 const size_t replacementLength = replacement.length();
2071 size_t index = 0;
2072 while ((index = text.find(matchFunction, index)) != kNotFound) {
2073 text.replace(index, 1, replacement);
2074 index += replacementLength;
2075 }
2076 }
2077
2078 void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo at y, bool fill, float maxWidth, bool useMaxWidth) 2095 void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo at y, bool fill, float maxWidth, bool useMaxWidth)
2079 { 2096 {
2080 // The style resolution required for rendering text is not available in fram e-less documents. 2097 // The style resolution required for rendering text is not available in fram e-less documents.
2081 if (!canvas()->document().frame()) 2098 if (!canvas()->document().frame())
2082 return; 2099 return;
2083 2100
2084 // accessFont needs the style to be up to date, but updating style can cause script to run, 2101 // accessFont needs the style to be up to date, but updating style can cause script to run,
2085 // (e.g. due to autofocus) which can free the GraphicsContext, so update sty le before grabbing 2102 // (e.g. due to autofocus) which can free the GraphicsContext, so update sty le before grabbing
2086 // the GraphicsContext. 2103 // the GraphicsContext.
2087 canvas()->document().updateRenderTreeIfNeeded(); 2104 canvas()->document().updateRenderTreeIfNeeded();
(...skipping 14 matching lines...) Expand all
2102 return; 2119 return;
2103 2120
2104 gradient = c->fillGradient(); 2121 gradient = c->fillGradient();
2105 if (fill && gradient && gradient->isZeroSize()) 2122 if (fill && gradient && gradient->isZeroSize())
2106 return; 2123 return;
2107 2124
2108 FontCachePurgePreventer fontCachePurgePreventer; 2125 FontCachePurgePreventer fontCachePurgePreventer;
2109 2126
2110 const Font& font = accessFont(); 2127 const Font& font = accessFont();
2111 const FontMetrics& fontMetrics = font.fontMetrics(); 2128 const FontMetrics& fontMetrics = font.fontMetrics();
2112 // According to spec, all the space characters must be replaced with U+0020 SPACE characters. 2129 String normalizedText = normalizeSpaces(text);
2113 String normalizedText = text;
2114 replaceCharacterInString(normalizedText, isSpaceOrNewline, " ");
2115 2130
2116 // FIXME: Need to turn off font smoothing. 2131 // FIXME: Need to turn off font smoothing.
2117 2132
2118 RenderStyle* computedStyle = canvas()->computedStyle(); 2133 RenderStyle* computedStyle = canvas()->computedStyle();
2119 TextDirection direction = computedStyle ? computedStyle->direction() : LTR; 2134 TextDirection direction = computedStyle ? computedStyle->direction() : LTR;
2120 bool isRTL = direction == RTL; 2135 bool isRTL = direction == RTL;
2121 bool override = computedStyle ? isOverride(computedStyle->unicodeBidi()) : f alse; 2136 bool override = computedStyle ? isOverride(computedStyle->unicodeBidi()) : f alse;
2122 2137
2123 TextRun textRun(normalizedText, 0, 0, TextRun::AllowTrailingExpansion, direc tion, override, true, TextRun::NoRounding); 2138 TextRun textRun(normalizedText, 0, 0, TextRun::AllowTrailingExpansion, direc tion, override, true, TextRun::NoRounding);
2124 // Draw the item text at the correct point. 2139 // Draw the item text at the correct point.
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
2370 c->setAlphaAsFloat(1.0); 2385 c->setAlphaAsFloat(1.0);
2371 c->clearShadow(); 2386 c->clearShadow();
2372 c->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal); 2387 c->setCompositeOperation(CompositeSourceOver, blink::WebBlendModeNormal);
2373 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor); 2388 c->drawFocusRing(path, focusRingWidth, focusRingOutline, focusRingColor);
2374 c->restore(); 2389 c->restore();
2375 2390
2376 didDraw(dirtyRect); 2391 didDraw(dirtyRect);
2377 } 2392 }
2378 2393
2379 } // namespace WebCore 2394 } // namespace WebCore
OLDNEW
« no previous file with comments | « LayoutTests/fast/canvas/canvas-text-space-characters.html ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698