Changeset 219970 in webkit
- Timestamp:
- Jul 26, 2017, 4:53:26 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 2 added
- 7 edited
-
LayoutTests/ChangeLog (modified) (1 diff)
-
LayoutTests/fast/canvas/canvas-measureText-2-expected.txt (added)
-
LayoutTests/fast/canvas/canvas-measureText-2.html (added)
-
Source/WebCore/ChangeLog (modified) (1 diff)
-
Source/WebCore/html/TextMetrics.h (modified) (1 diff)
-
Source/WebCore/html/TextMetrics.idl (modified) (1 diff)
-
Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp (modified) (4 diffs)
-
Source/WebCore/html/canvas/CanvasRenderingContext2D.h (modified) (2 diffs)
-
Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r219968 r219970 1 2017-07-26 Arnaud Renevier <a.renevier@sisa.samsung.com> and Fujii Hironori <Hironori.Fujii@sony.com> 2 3 Implement new TextMetrics, returned by canvas measureText() 4 https://bugs.webkit.org/show_bug.cgi?id=82798 5 6 Reviewed by Dean Jackson. 7 8 Create a test that checks that: 9 - ascent + descent is greater than zero 10 - actualBoundingBoxLeft + actualBoundingBoxRight is somewhere 11 quite close to width 12 - when baseline is top, emHeightAscent is 0 (respectively 13 bottom/emHeightDescent) 14 - when baseline is hanging, hangingBaseline in 0 (respectively 15 alphabetic and ideographic) 16 - order of different vertical measures (for example, 17 emHeightAscent is always higher that alphabeticBaseline) 18 19 * fast/canvas/canvas-measureText-2-expected.txt: Added. 20 * fast/canvas/canvas-measureText-2.html: Added. 21 1 22 2017-07-26 Matt Lewis <jlewis3@apple.com> 2 23 -
trunk/Source/WebCore/ChangeLog
r219964 r219970 1 2017-07-26 Arnaud Renevier <a.renevier@sisa.samsung.com> and Fujii Hironori <Hironori.Fujii@sony.com> 2 3 Implement new TextMetrics, returned by canvas measureText() 4 https://bugs.webkit.org/show_bug.cgi?id=82798 5 <rdar://problem/11159332> 6 7 Reviewed by Dean Jackson. 8 9 The specification: https://html.spec.whatwg.org/multipage/canvas.html#dom-context-2d-measuretext 10 11 Add new attributes to TextMetrics. 12 13 Add a new method textOffset() of CanvasRenderingContext2D by 14 extracting from drawTextInternal() to use the same horizontal and 15 vertical offsets of a text in both drawTextInternal() and 16 measureText(). 17 18 Test: fast/canvas/canvas-measureText-2.html 19 20 * html/TextMetrics.h: 21 (WebCore::TextMetrics::actualBoundingBoxLeft): 22 (WebCore::TextMetrics::setActualBoundingBoxLeft): 23 (WebCore::TextMetrics::actualBoundingBoxRight): 24 (WebCore::TextMetrics::setActualBoundingBoxRight): 25 (WebCore::TextMetrics::fontBoundingBoxAscent): 26 (WebCore::TextMetrics::setFontBoundingBoxAscent): 27 (WebCore::TextMetrics::fontBoundingBoxDescent): 28 (WebCore::TextMetrics::setFontBoundingBoxDescent): 29 (WebCore::TextMetrics::actualBoundingBoxAscent): 30 (WebCore::TextMetrics::setActualBoundingBoxAscent): 31 (WebCore::TextMetrics::actualBoundingBoxDescent): 32 (WebCore::TextMetrics::setActualBoundingBoxDescent): 33 (WebCore::TextMetrics::emHeightAscent): 34 (WebCore::TextMetrics::setEmHeightAscent): 35 (WebCore::TextMetrics::emHeightDescent): 36 (WebCore::TextMetrics::setEmHeightDescent): 37 (WebCore::TextMetrics::hangingBaseline): 38 (WebCore::TextMetrics::setHangingBaseline): 39 (WebCore::TextMetrics::alphabeticBaseline): 40 (WebCore::TextMetrics::setAlphabeticBaseline): 41 (WebCore::TextMetrics::ideographicBaseline): 42 (WebCore::TextMetrics::setIdeographicBaseline): 43 Added getters and setters. 44 (WebCore::TextMetrics::TextMetrics): Deleted. 45 * html/TextMetrics.idl: Added new attributes. 46 * html/canvas/CanvasRenderingContext2D.cpp: 47 (WebCore::CanvasRenderingContext2D::FontProxy::fontMetrics): 48 Changed the return value type to a const reference of FontMetrics 49 not to copy it. 50 (WebCore::CanvasRenderingContext2D::FontProxy::width): 51 Added the second arguemnt of GlyphOverflow type. 52 (WebCore::CanvasRenderingContext2D::measureText): Calculate and 53 set the new attributes of TextMetrics. 54 (WebCore::CanvasRenderingContext2D::textOffset): Extracted from drawTextInternal. 55 (WebCore::CanvasRenderingContext2D::drawTextInternal): Removed the 56 offset calculation code and call textOffset. 57 * html/canvas/CanvasRenderingContext2D.h: Added the method 58 declaration of textOffset. Change types of fontMetrics and width 59 methods. 60 * platform/graphics/cairo/FontCairoHarfbuzzNG.cpp: 61 (WebCore::FontCascade::floatWidthForComplexText): Added a dummy 62 implementation of calculating GlyphOverflow. 63 1 64 2017-07-26 Devin Rousso <drousso@apple.com> 2 65 -
trunk/Source/WebCore/html/TextMetrics.h
r208179 r219970 38 38 void setWidth(float w) { m_width = w; } 39 39 40 float actualBoundingBoxLeft() const { return m_actualBoundingBoxLeft; } 41 void setActualBoundingBoxLeft(float value) { m_actualBoundingBoxLeft = value; } 42 43 float actualBoundingBoxRight() const { return m_actualBoundingBoxRight; } 44 void setActualBoundingBoxRight(float value) { m_actualBoundingBoxRight = value; } 45 46 float fontBoundingBoxAscent() const { return m_fontBoundingBoxAscent; } 47 void setFontBoundingBoxAscent(float value) { m_fontBoundingBoxAscent = value; } 48 49 float fontBoundingBoxDescent() const { return m_fontBoundingBoxDescent; } 50 void setFontBoundingBoxDescent(float value) { m_fontBoundingBoxDescent = value; } 51 52 float actualBoundingBoxAscent() const { return m_actualBoundingBoxAscent; } 53 void setActualBoundingBoxAscent(float value) { m_actualBoundingBoxAscent = value; } 54 55 float actualBoundingBoxDescent() const { return m_actualBoundingBoxDescent; } 56 void setActualBoundingBoxDescent(float value) { m_actualBoundingBoxDescent = value; } 57 58 float emHeightAscent() const { return m_emHeightAscent; } 59 void setEmHeightAscent(float value) { m_emHeightAscent = value; } 60 61 float emHeightDescent() const { return m_emHeightDescent; } 62 void setEmHeightDescent(float value) { m_emHeightDescent = value; } 63 64 float hangingBaseline() const { return m_hangingBaseline; } 65 void setHangingBaseline(float value) { m_hangingBaseline = value; } 66 67 float alphabeticBaseline() const { return m_alphabeticBaseline; } 68 void setAlphabeticBaseline(float value) { m_alphabeticBaseline = value; } 69 70 float ideographicBaseline() const { return m_ideographicBaseline; } 71 void setIdeographicBaseline(float value) { m_ideographicBaseline = value; } 72 40 73 private: 41 TextMetrics() 42 : m_width(0) 43 { } 44 45 float m_width; 74 float m_width { 0 }; 75 float m_actualBoundingBoxLeft { 0 }; 76 float m_actualBoundingBoxRight { 0 }; 77 float m_fontBoundingBoxAscent { 0 }; 78 float m_fontBoundingBoxDescent { 0 }; 79 float m_actualBoundingBoxAscent { 0 }; 80 float m_actualBoundingBoxDescent { 0 }; 81 float m_emHeightAscent { 0 }; 82 float m_emHeightDescent { 0 }; 83 float m_hangingBaseline { 0 }; 84 float m_alphabeticBaseline { 0 }; 85 float m_ideographicBaseline { 0 }; 46 86 }; 47 87 -
trunk/Source/WebCore/html/TextMetrics.idl
r168302 r219970 27 27 ] interface TextMetrics { 28 28 readonly attribute unrestricted float width; 29 readonly attribute unrestricted float actualBoundingBoxLeft; 30 readonly attribute unrestricted float actualBoundingBoxRight; 31 readonly attribute unrestricted float fontBoundingBoxAscent; 32 readonly attribute unrestricted float fontBoundingBoxDescent; 33 readonly attribute unrestricted float actualBoundingBoxAscent; 34 readonly attribute unrestricted float actualBoundingBoxDescent; 35 readonly attribute unrestricted float emHeightAscent; 36 readonly attribute unrestricted float emHeightDescent; 37 readonly attribute unrestricted float hangingBaseline; 38 readonly attribute unrestricted float alphabeticBaseline; 39 readonly attribute unrestricted float ideographicBaseline; 29 40 }; 30 41 -
trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.cpp
r219964 r219970 329 329 } 330 330 331 inline FontMetricsCanvasRenderingContext2D::FontProxy::fontMetrics() const331 inline const FontMetrics& CanvasRenderingContext2D::FontProxy::fontMetrics() const 332 332 { 333 333 return m_font.fontMetrics(); … … 339 339 } 340 340 341 inline float CanvasRenderingContext2D::FontProxy::width(const TextRun& textRun ) const342 { 343 return m_font.width(textRun );341 inline float CanvasRenderingContext2D::FontProxy::width(const TextRun& textRun, GlyphOverflow* overflow) const 342 { 343 return m_font.width(textRun, 0, overflow); 344 344 } 345 345 … … 2345 2345 normalizeSpaces(normalizedText); 2346 2346 2347 metrics->setWidth(fontProxy().width(TextRun(normalizedText)));2348 2349 return metrics;2350 }2351 2352 void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, float y, bool fill, std::optional<float> maxWidth)2353 {2354 auto& fontProxy = this->fontProxy();2355 const auto& fontMetrics = fontProxy.fontMetrics();2356 2357 auto* c = drawingContext();2358 if (!c)2359 return;2360 if (!state().hasInvertibleTransform)2361 return;2362 if (!std::isfinite(x) | !std::isfinite(y))2363 return;2364 if (maxWidth && (!std::isfinite(maxWidth.value()) || maxWidth.value() <= 0))2365 return;2366 2367 // If gradient size is zero, then paint nothing.2368 auto* gradient = c->strokeGradient();2369 if (!fill && gradient && gradient->isZeroSize())2370 return;2371 2372 gradient = c->fillGradient();2373 if (fill && gradient && gradient->isZeroSize())2374 return;2375 2376 String normalizedText = text;2377 normalizeSpaces(normalizedText);2378 2379 // FIXME: Need to turn off font smoothing.2380 2381 2347 const RenderStyle* computedStyle; 2382 2348 auto direction = toTextDirection(state().direction, &computedStyle); 2383 bool isRTL = direction == RTL;2384 2349 bool override = computedStyle ? isOverride(computedStyle->unicodeBidi()) : false; 2385 2350 2386 2351 TextRun textRun(normalizedText, 0, 0, AllowTrailingExpansion, direction, override, true); 2387 // Draw the item text at the correct point. 2388 FloatPoint location(x, y); 2352 auto& font = fontProxy(); 2353 auto& fontMetrics = font.fontMetrics(); 2354 2355 GlyphOverflow glyphOverflow; 2356 glyphOverflow.computeBounds = true; 2357 float fontWidth = font.width(textRun, &glyphOverflow); 2358 metrics->setWidth(fontWidth); 2359 2360 FloatPoint offset = textOffset(fontWidth, direction); 2361 2362 metrics->setActualBoundingBoxAscent(glyphOverflow.top - offset.y()); 2363 metrics->setActualBoundingBoxDescent(glyphOverflow.bottom + offset.y()); 2364 metrics->setFontBoundingBoxAscent(fontMetrics.ascent() - offset.y()); 2365 metrics->setFontBoundingBoxDescent(fontMetrics.descent() + offset.y()); 2366 metrics->setEmHeightAscent(fontMetrics.ascent() - offset.y()); 2367 metrics->setEmHeightDescent(fontMetrics.descent() + offset.y()); 2368 metrics->setHangingBaseline(fontMetrics.ascent() - offset.y()); 2369 metrics->setAlphabeticBaseline(-offset.y()); 2370 metrics->setIdeographicBaseline(-fontMetrics.descent() - offset.y()); 2371 2372 metrics->setActualBoundingBoxLeft(glyphOverflow.left - offset.x()); 2373 metrics->setActualBoundingBoxRight(fontWidth + glyphOverflow.right + offset.x()); 2374 2375 return metrics; 2376 } 2377 2378 FloatPoint CanvasRenderingContext2D::textOffset(float width, TextDirection direction) 2379 { 2380 auto& fontMetrics = fontProxy().fontMetrics(); 2381 FloatPoint offset; 2382 2389 2383 switch (state().textBaseline) { 2390 2384 case TopTextBaseline: 2391 2385 case HangingTextBaseline: 2392 location.setY(y +fontMetrics.ascent());2386 offset.setY(fontMetrics.ascent()); 2393 2387 break; 2394 2388 case BottomTextBaseline: 2395 2389 case IdeographicTextBaseline: 2396 location.setY(y -fontMetrics.descent());2390 offset.setY(-fontMetrics.descent()); 2397 2391 break; 2398 2392 case MiddleTextBaseline: 2399 location.setY(y - fontMetrics.descent() + fontMetrics.height() / 2);2393 offset.setY(fontMetrics.height() / 2 - fontMetrics.descent()); 2400 2394 break; 2401 2395 case AlphabeticTextBaseline: 2402 2396 default: 2403 // Do nothing.2404 2397 break; 2405 2398 } 2406 2399 2407 float fontWidth = fontProxy.width(TextRun(normalizedText, 0, 0, AllowTrailingExpansion, direction, override)); 2408 2409 bool useMaxWidth = maxWidth && maxWidth.value() < fontWidth; 2410 float width = useMaxWidth ? maxWidth.value() : fontWidth; 2411 2400 bool isRTL = direction == RTL; 2412 2401 auto align = state().textAlign; 2413 2402 if (align == StartTextAlign) … … 2418 2407 switch (align) { 2419 2408 case CenterTextAlign: 2420 location.setX(location.x() -width / 2);2409 offset.setX(-width / 2); 2421 2410 break; 2422 2411 case RightTextAlign: 2423 location.setX(location.x() -width);2412 offset.setX(-width); 2424 2413 break; 2425 2414 default: 2426 2415 break; 2427 2416 } 2417 return offset; 2418 } 2419 2420 void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, float y, bool fill, std::optional<float> maxWidth) 2421 { 2422 auto& fontProxy = this->fontProxy(); 2423 const auto& fontMetrics = fontProxy.fontMetrics(); 2424 2425 auto* c = drawingContext(); 2426 if (!c) 2427 return; 2428 if (!state().hasInvertibleTransform) 2429 return; 2430 if (!std::isfinite(x) | !std::isfinite(y)) 2431 return; 2432 if (maxWidth && (!std::isfinite(maxWidth.value()) || maxWidth.value() <= 0)) 2433 return; 2434 2435 // If gradient size is zero, then paint nothing. 2436 auto* gradient = c->strokeGradient(); 2437 if (!fill && gradient && gradient->isZeroSize()) 2438 return; 2439 2440 gradient = c->fillGradient(); 2441 if (fill && gradient && gradient->isZeroSize()) 2442 return; 2443 2444 String normalizedText = text; 2445 normalizeSpaces(normalizedText); 2446 2447 // FIXME: Need to turn off font smoothing. 2448 2449 const RenderStyle* computedStyle; 2450 auto direction = toTextDirection(state().direction, &computedStyle); 2451 bool override = computedStyle ? isOverride(computedStyle->unicodeBidi()) : false; 2452 2453 TextRun textRun(normalizedText, 0, 0, AllowTrailingExpansion, direction, override, true); 2454 float fontWidth = fontProxy.width(textRun); 2455 bool useMaxWidth = maxWidth && maxWidth.value() < fontWidth; 2456 float width = useMaxWidth ? maxWidth.value() : fontWidth; 2457 FloatPoint location(x, y); 2458 location += textOffset(width, direction); 2428 2459 2429 2460 // The slop built in to this mask rect matches the heuristic used in FontCGWin.cpp for GDI text. -
trunk/Source/WebCore/html/canvas/CanvasRenderingContext2D.h
r219964 r219970 251 251 bool realized() const { return m_font.fontSelector(); } 252 252 void initialize(FontSelector&, const RenderStyle&); 253 FontMetricsfontMetrics() const;253 const FontMetrics& fontMetrics() const; 254 254 const FontCascadeDescription& fontDescription() const; 255 float width(const TextRun& ) const;255 float width(const TextRun&, GlyphOverflow* = 0) const; 256 256 void drawBidiText(GraphicsContext&, const TextRun&, const FloatPoint&, FontCascade::CustomFontNotReadyAction) const; 257 257 … … 391 391 TextDirection toTextDirection(Direction, const RenderStyle** computedStyle = nullptr) const; 392 392 393 FloatPoint textOffset(float width, TextDirection); 394 393 395 #if ENABLE(ACCELERATED_2D_CANVAS) 394 396 PlatformLayer* platformLayer() const override; -
trunk/Source/WebCore/platform/graphics/cairo/FontCairoHarfbuzzNG.cpp
r211836 r219970 63 63 } 64 64 65 float FontCascade::floatWidthForComplexText(const TextRun& run, HashSet<const Font*>*, GlyphOverflow* ) const65 float FontCascade::floatWidthForComplexText(const TextRun& run, HashSet<const Font*>*, GlyphOverflow* glyphOverflow) const 66 66 { 67 if (glyphOverflow) { 68 // FIXME: Calculate the actual values rather than just the font's ascent and descent 69 glyphOverflow->top = glyphOverflow->computeBounds ? fontMetrics().ascent() : 0; 70 glyphOverflow->bottom = glyphOverflow->computeBounds ? fontMetrics().descent() : 0; 71 glyphOverflow->left = 0; 72 glyphOverflow->right = 0; 73 } 67 74 HarfBuzzShaper shaper(this, run); 68 75 if (shaper.shape())
Note:
See TracChangeset
for help on using the changeset viewer.