 Chromium Code Reviews
 Chromium Code Reviews Issue 468483003:
  Implement canvas2d direction attribute  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/blink.git@master
    
  
    Issue 468483003:
  Implement canvas2d direction attribute  (Closed) 
  Base URL: https://chromium.googlesource.com/chromium/blink.git@master| OLD | NEW | 
|---|---|
| 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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 76 static const char defaultFontFamily[] = "sans-serif"; | 76 static const char defaultFontFamily[] = "sans-serif"; | 
| 77 static const char defaultFont[] = "10px sans-serif"; | 77 static const char defaultFont[] = "10px sans-serif"; | 
| 78 static const double TryRestoreContextInterval = 0.5; | 78 static const double TryRestoreContextInterval = 0.5; | 
| 79 static const unsigned MaxTryRestoreContextAttempts = 4; | 79 static const unsigned MaxTryRestoreContextAttempts = 4; | 
| 80 | 80 | 
| 81 static bool contextLostRestoredEventsEnabled() | 81 static bool contextLostRestoredEventsEnabled() | 
| 82 { | 82 { | 
| 83 return RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); | 83 return RuntimeEnabledFeatures::experimentalCanvasFeaturesEnabled(); | 
| 84 } | 84 } | 
| 85 | 85 | 
| 86 static inline TextDirection inheritedDirection(HTMLCanvasElement& canvasElement) | |
| 87 { | |
| 88 canvasElement.document().updateRenderTreeIfNeeded(); | |
| 89 RenderStyle* computedStyle = canvasElement.computedStyle(); | |
| 90 return computedStyle ? computedStyle->direction() : LTR; | |
| 91 } | |
| 92 | |
| 86 CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, co nst Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode) | 93 CanvasRenderingContext2D::CanvasRenderingContext2D(HTMLCanvasElement* canvas, co nst Canvas2DContextAttributes* attrs, bool usesCSSCompatibilityParseMode) | 
| 87 : CanvasRenderingContext(canvas) | 94 : CanvasRenderingContext(canvas) | 
| 88 , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode) | 95 , m_usesCSSCompatibilityParseMode(usesCSSCompatibilityParseMode) | 
| 89 , m_hasAlpha(!attrs || attrs->alpha()) | 96 , m_hasAlpha(!attrs || attrs->alpha()) | 
| 90 , m_isContextLost(false) | 97 , m_isContextLost(false) | 
| 91 , m_contextRestorable(true) | 98 , m_contextRestorable(true) | 
| 92 , m_storageMode(!attrs ? PersistentStorage : attrs->parsedStorage()) | 99 , m_storageMode(!attrs ? PersistentStorage : attrs->parsedStorage()) | 
| 93 , m_tryRestoreContextAttemptCount(0) | 100 , m_tryRestoreContextAttemptCount(0) | 
| 94 , m_dispatchContextLostEventTimer(this, &CanvasRenderingContext2D::dispatchC ontextLostEvent) | 101 , m_dispatchContextLostEventTimer(this, &CanvasRenderingContext2D::dispatchC ontextLostEvent) | 
| 95 , m_dispatchContextRestoredEventTimer(this, &CanvasRenderingContext2D::dispa tchContextRestoredEvent) | 102 , m_dispatchContextRestoredEventTimer(this, &CanvasRenderingContext2D::dispa tchContextRestoredEvent) | 
| 96 , m_tryRestoreContextEventTimer(this, &CanvasRenderingContext2D::tryRestoreC ontextEvent) | 103 , m_tryRestoreContextEventTimer(this, &CanvasRenderingContext2D::tryRestoreC ontextEvent) | 
| 97 { | 104 { | 
| 98 m_stateStack.append(adoptPtrWillBeNoop(new State())); | 105 m_stateStack.append(adoptPtrWillBeNoop(new State(inheritedDirection(*canvas) ))); | 
| 99 ScriptWrappable::init(this); | 106 ScriptWrappable::init(this); | 
| 100 } | 107 } | 
| 101 | 108 | 
| 102 void CanvasRenderingContext2D::unwindStateStack() | 109 void CanvasRenderingContext2D::unwindStateStack() | 
| 103 { | 110 { | 
| 104 if (size_t stackSize = m_stateStack.size()) { | 111 if (size_t stackSize = m_stateStack.size()) { | 
| 105 if (GraphicsContext* context = canvas()->existingDrawingContext()) { | 112 if (GraphicsContext* context = canvas()->existingDrawingContext()) { | 
| 106 while (--stackSize) | 113 while (--stackSize) | 
| 107 context->restore(); | 114 context->restore(); | 
| 108 } | 115 } | 
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 223 RefPtrWillBeRawPtr<Event> event(Event::create(EventTypeNames::contextres tored)); | 230 RefPtrWillBeRawPtr<Event> event(Event::create(EventTypeNames::contextres tored)); | 
| 224 canvas()->dispatchEvent(event); | 231 canvas()->dispatchEvent(event); | 
| 225 } | 232 } | 
| 226 } | 233 } | 
| 227 | 234 | 
| 228 void CanvasRenderingContext2D::reset() | 235 void CanvasRenderingContext2D::reset() | 
| 229 { | 236 { | 
| 230 validateStateStack(); | 237 validateStateStack(); | 
| 231 unwindStateStack(); | 238 unwindStateStack(); | 
| 232 m_stateStack.resize(1); | 239 m_stateStack.resize(1); | 
| 233 m_stateStack.first() = adoptPtrWillBeNoop(new State()); | 240 m_stateStack.first() = adoptPtrWillBeNoop(new State(inheritedDirection(*canv as()))); | 
| 234 m_path.clear(); | 241 m_path.clear(); | 
| 235 validateStateStack(); | 242 validateStateStack(); | 
| 236 } | 243 } | 
| 237 | 244 | 
| 238 // Important: Several of these properties are also stored in GraphicsContext's | 245 // Important: Several of these properties are also stored in GraphicsContext's | 
| 239 // StrokeData. The default values that StrokeData uses may not the same values | 246 // StrokeData. The default values that StrokeData uses may not the same values | 
| 240 // that the canvas 2d spec specifies. Make sure to sync the initial state of the | 247 // that the canvas 2d spec specifies. Make sure to sync the initial state of the | 
| 241 // GraphicsContext in HTMLCanvasElement::createImageBuffer()! | 248 // GraphicsContext in HTMLCanvasElement::createImageBuffer()! | 
| 242 CanvasRenderingContext2D::State::State() | 249 CanvasRenderingContext2D::State::State(TextDirection direction) | 
| 243 : m_unrealizedSaveCount(0) | 250 : m_unrealizedSaveCount(0) | 
| 244 , m_strokeStyle(CanvasStyle::createFromRGBA(Color::black)) | 251 , m_strokeStyle(CanvasStyle::createFromRGBA(Color::black)) | 
| 245 , m_fillStyle(CanvasStyle::createFromRGBA(Color::black)) | 252 , m_fillStyle(CanvasStyle::createFromRGBA(Color::black)) | 
| 246 , m_lineWidth(1) | 253 , m_lineWidth(1) | 
| 247 , m_lineCap(ButtCap) | 254 , m_lineCap(ButtCap) | 
| 248 , m_lineJoin(MiterJoin) | 255 , m_lineJoin(MiterJoin) | 
| 249 , m_miterLimit(10) | 256 , m_miterLimit(10) | 
| 250 , m_shadowBlur(0) | 257 , m_shadowBlur(0) | 
| 251 , m_shadowColor(Color::transparent) | 258 , m_shadowColor(Color::transparent) | 
| 252 , m_globalAlpha(1) | 259 , m_globalAlpha(1) | 
| 253 , m_globalComposite(CompositeSourceOver) | 260 , m_globalComposite(CompositeSourceOver) | 
| 254 , m_globalBlend(blink::WebBlendModeNormal) | 261 , m_globalBlend(blink::WebBlendModeNormal) | 
| 255 , m_invertibleCTM(true) | 262 , m_invertibleCTM(true) | 
| 256 , m_lineDashOffset(0) | 263 , m_lineDashOffset(0) | 
| 257 , m_imageSmoothingEnabled(true) | 264 , m_imageSmoothingEnabled(true) | 
| 258 , m_textAlign(StartTextAlign) | 265 , m_textAlign(StartTextAlign) | 
| 259 , m_textBaseline(AlphabeticTextBaseline) | 266 , m_textBaseline(AlphabeticTextBaseline) | 
| 267 , m_direction(direction) | |
| 260 , m_unparsedFont(defaultFont) | 268 , m_unparsedFont(defaultFont) | 
| 261 , m_realizedFont(false) | 269 , m_realizedFont(false) | 
| 262 , m_hasClip(false) | 270 , m_hasClip(false) | 
| 263 { | 271 { | 
| 264 } | 272 } | 
| 265 | 273 | 
| 266 CanvasRenderingContext2D::State::State(const State& other) | 274 CanvasRenderingContext2D::State::State(const State& other) | 
| 267 : CSSFontSelectorClient() | 275 : CSSFontSelectorClient() | 
| 268 , m_unrealizedSaveCount(other.m_unrealizedSaveCount) | 276 , m_unrealizedSaveCount(other.m_unrealizedSaveCount) | 
| 269 , m_unparsedStrokeColor(other.m_unparsedStrokeColor) | 277 , m_unparsedStrokeColor(other.m_unparsedStrokeColor) | 
| 270 , m_unparsedFillColor(other.m_unparsedFillColor) | 278 , m_unparsedFillColor(other.m_unparsedFillColor) | 
| 271 , m_strokeStyle(other.m_strokeStyle) | 279 , m_strokeStyle(other.m_strokeStyle) | 
| 272 , m_fillStyle(other.m_fillStyle) | 280 , m_fillStyle(other.m_fillStyle) | 
| 273 , m_lineWidth(other.m_lineWidth) | 281 , m_lineWidth(other.m_lineWidth) | 
| 274 , m_lineCap(other.m_lineCap) | 282 , m_lineCap(other.m_lineCap) | 
| 275 , m_lineJoin(other.m_lineJoin) | 283 , m_lineJoin(other.m_lineJoin) | 
| 276 , m_miterLimit(other.m_miterLimit) | 284 , m_miterLimit(other.m_miterLimit) | 
| 277 , m_shadowOffset(other.m_shadowOffset) | 285 , m_shadowOffset(other.m_shadowOffset) | 
| 278 , m_shadowBlur(other.m_shadowBlur) | 286 , m_shadowBlur(other.m_shadowBlur) | 
| 279 , m_shadowColor(other.m_shadowColor) | 287 , m_shadowColor(other.m_shadowColor) | 
| 280 , m_globalAlpha(other.m_globalAlpha) | 288 , m_globalAlpha(other.m_globalAlpha) | 
| 281 , m_globalComposite(other.m_globalComposite) | 289 , m_globalComposite(other.m_globalComposite) | 
| 282 , m_globalBlend(other.m_globalBlend) | 290 , m_globalBlend(other.m_globalBlend) | 
| 283 , m_transform(other.m_transform) | 291 , m_transform(other.m_transform) | 
| 284 , m_invertibleCTM(other.m_invertibleCTM) | 292 , m_invertibleCTM(other.m_invertibleCTM) | 
| 285 , m_lineDashOffset(other.m_lineDashOffset) | 293 , m_lineDashOffset(other.m_lineDashOffset) | 
| 286 , m_imageSmoothingEnabled(other.m_imageSmoothingEnabled) | 294 , m_imageSmoothingEnabled(other.m_imageSmoothingEnabled) | 
| 287 , m_textAlign(other.m_textAlign) | 295 , m_textAlign(other.m_textAlign) | 
| 288 , m_textBaseline(other.m_textBaseline) | 296 , m_textBaseline(other.m_textBaseline) | 
| 297 , m_direction(other.m_direction) | |
| 289 , m_unparsedFont(other.m_unparsedFont) | 298 , m_unparsedFont(other.m_unparsedFont) | 
| 290 , m_font(other.m_font) | 299 , m_font(other.m_font) | 
| 291 , m_realizedFont(other.m_realizedFont) | 300 , m_realizedFont(other.m_realizedFont) | 
| 292 , m_hasClip(other.m_hasClip) | 301 , m_hasClip(other.m_hasClip) | 
| 293 { | 302 { | 
| 294 if (m_realizedFont) | 303 if (m_realizedFont) | 
| 295 static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalid ationCallbacks(this); | 304 static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalid ationCallbacks(this); | 
| 296 } | 305 } | 
| 297 | 306 | 
| 298 CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(cons t State& other) | 307 CanvasRenderingContext2D::State& CanvasRenderingContext2D::State::operator=(cons t State& other) | 
| (...skipping 19 matching lines...) Expand all Loading... | |
| 318 m_shadowBlur = other.m_shadowBlur; | 327 m_shadowBlur = other.m_shadowBlur; | 
| 319 m_shadowColor = other.m_shadowColor; | 328 m_shadowColor = other.m_shadowColor; | 
| 320 m_globalAlpha = other.m_globalAlpha; | 329 m_globalAlpha = other.m_globalAlpha; | 
| 321 m_globalComposite = other.m_globalComposite; | 330 m_globalComposite = other.m_globalComposite; | 
| 322 m_globalBlend = other.m_globalBlend; | 331 m_globalBlend = other.m_globalBlend; | 
| 323 m_transform = other.m_transform; | 332 m_transform = other.m_transform; | 
| 324 m_invertibleCTM = other.m_invertibleCTM; | 333 m_invertibleCTM = other.m_invertibleCTM; | 
| 325 m_imageSmoothingEnabled = other.m_imageSmoothingEnabled; | 334 m_imageSmoothingEnabled = other.m_imageSmoothingEnabled; | 
| 326 m_textAlign = other.m_textAlign; | 335 m_textAlign = other.m_textAlign; | 
| 327 m_textBaseline = other.m_textBaseline; | 336 m_textBaseline = other.m_textBaseline; | 
| 337 m_direction = other.m_direction; | |
| 328 m_unparsedFont = other.m_unparsedFont; | 338 m_unparsedFont = other.m_unparsedFont; | 
| 329 m_font = other.m_font; | 339 m_font = other.m_font; | 
| 330 m_realizedFont = other.m_realizedFont; | 340 m_realizedFont = other.m_realizedFont; | 
| 331 m_hasClip = other.m_hasClip; | 341 m_hasClip = other.m_hasClip; | 
| 332 | 342 | 
| 333 if (m_realizedFont) | 343 if (m_realizedFont) | 
| 334 static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalid ationCallbacks(this); | 344 static_cast<CSSFontSelector*>(m_font.fontSelector())->registerForInvalid ationCallbacks(this); | 
| 335 | 345 | 
| 336 return *this; | 346 return *this; | 
| 337 } | 347 } | 
| (...skipping 1671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2009 { | 2019 { | 
| 2010 TextBaseline baseline; | 2020 TextBaseline baseline; | 
| 2011 if (!parseTextBaseline(s, baseline)) | 2021 if (!parseTextBaseline(s, baseline)) | 
| 2012 return; | 2022 return; | 
| 2013 if (state().m_textBaseline == baseline) | 2023 if (state().m_textBaseline == baseline) | 
| 2014 return; | 2024 return; | 
| 2015 realizeSaves(); | 2025 realizeSaves(); | 
| 2016 modifiableState().m_textBaseline = baseline; | 2026 modifiableState().m_textBaseline = baseline; | 
| 2017 } | 2027 } | 
| 2018 | 2028 | 
| 2029 String CanvasRenderingContext2D::direction() const | |
| 2030 { | |
| 2031 return state().m_direction == RTL ? "rtl" : "ltr"; | |
| 2032 } | |
| 2033 | |
| 2034 void CanvasRenderingContext2D::setDirection(const String& directionString) | |
| 2035 { | |
| 2036 TextDirection direction; | |
| 2037 if (directionString == "inherit") | |
| 2038 direction = inheritedDirection(*canvas()); | |
| 
esprehn
2014/08/19 17:46:53
This is now how inheritance is supposed to work, i
 | |
| 2039 else if (directionString == "rtl") | |
| 2040 direction = RTL; | |
| 2041 else if (directionString == "ltr") | |
| 2042 direction = LTR; | |
| 2043 else | |
| 2044 return; | |
| 2045 | |
| 2046 realizeSaves(); | |
| 2047 modifiableState().m_direction = direction; | |
| 2048 } | |
| 2049 | |
| 2019 void CanvasRenderingContext2D::fillText(const String& text, float x, float y) | 2050 void CanvasRenderingContext2D::fillText(const String& text, float x, float y) | 
| 2020 { | 2051 { | 
| 2021 drawTextInternal(text, x, y, true); | 2052 drawTextInternal(text, x, y, true); | 
| 2022 } | 2053 } | 
| 2023 | 2054 | 
| 2024 void CanvasRenderingContext2D::fillText(const String& text, float x, float y, fl oat maxWidth) | 2055 void CanvasRenderingContext2D::fillText(const String& text, float x, float y, fl oat maxWidth) | 
| 2025 { | 2056 { | 
| 2026 drawTextInternal(text, x, y, true, maxWidth, true); | 2057 drawTextInternal(text, x, y, true, maxWidth, true); | 
| 2027 } | 2058 } | 
| 2028 | 2059 | 
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2136 | 2167 | 
| 2137 FontCachePurgePreventer fontCachePurgePreventer; | 2168 FontCachePurgePreventer fontCachePurgePreventer; | 
| 2138 | 2169 | 
| 2139 const Font& font = accessFont(); | 2170 const Font& font = accessFont(); | 
| 2140 const FontMetrics& fontMetrics = font.fontMetrics(); | 2171 const FontMetrics& fontMetrics = font.fontMetrics(); | 
| 2141 String normalizedText = normalizeSpaces(text); | 2172 String normalizedText = normalizeSpaces(text); | 
| 2142 | 2173 | 
| 2143 // FIXME: Need to turn off font smoothing. | 2174 // FIXME: Need to turn off font smoothing. | 
| 2144 | 2175 | 
| 2145 RenderStyle* computedStyle = canvas()->computedStyle(); | 2176 RenderStyle* computedStyle = canvas()->computedStyle(); | 
| 2146 TextDirection direction = computedStyle ? computedStyle->direction() : LTR; | 2177 bool isRTL = state().m_direction == RTL; | 
| 2147 bool isRTL = direction == RTL; | |
| 2148 bool override = computedStyle ? isOverride(computedStyle->unicodeBidi()) : f alse; | 2178 bool override = computedStyle ? isOverride(computedStyle->unicodeBidi()) : f alse; | 
| 2149 | 2179 | 
| 2150 TextRun textRun(normalizedText, 0, 0, TextRun::AllowTrailingExpansion, direc tion, override, true); | 2180 TextRun textRun(normalizedText, 0, 0, TextRun::AllowTrailingExpansion, state ().m_direction, override, true); | 
| 2151 // Draw the item text at the correct point. | 2181 // Draw the item text at the correct point. | 
| 2152 FloatPoint location(x, y + getFontBaseline(fontMetrics)); | 2182 FloatPoint location(x, y + getFontBaseline(fontMetrics)); | 
| 2153 | 2183 | 
| 2154 float fontWidth = font.width(TextRun(normalizedText, 0, 0, TextRun::AllowTra ilingExpansion, direction, override)); | 2184 float fontWidth = font.width(TextRun(normalizedText, 0, 0, TextRun::AllowTra ilingExpansion, state().m_direction, override)); | 
| 2155 | 2185 | 
| 2156 useMaxWidth = (useMaxWidth && maxWidth < fontWidth); | 2186 useMaxWidth = (useMaxWidth && maxWidth < fontWidth); | 
| 2157 float width = useMaxWidth ? maxWidth : fontWidth; | 2187 float width = useMaxWidth ? maxWidth : fontWidth; | 
| 2158 | 2188 | 
| 2159 TextAlign align = state().m_textAlign; | 2189 TextAlign align = state().m_textAlign; | 
| 2160 if (align == StartTextAlign) | 2190 if (align == StartTextAlign) | 
| 2161 align = isRTL ? RightTextAlign : LeftTextAlign; | 2191 align = isRTL ? RightTextAlign : LeftTextAlign; | 
| 2162 else if (align == EndTextAlign) | 2192 else if (align == EndTextAlign) | 
| 2163 align = isRTL ? LeftTextAlign : RightTextAlign; | 2193 align = isRTL ? LeftTextAlign : RightTextAlign; | 
| 2164 | 2194 | 
| (...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2444 | 2474 | 
| 2445 unsigned CanvasRenderingContext2D::hitRegionsCount() const | 2475 unsigned CanvasRenderingContext2D::hitRegionsCount() const | 
| 2446 { | 2476 { | 
| 2447 if (m_hitRegionManager) | 2477 if (m_hitRegionManager) | 
| 2448 return m_hitRegionManager->getHitRegionsCount(); | 2478 return m_hitRegionManager->getHitRegionsCount(); | 
| 2449 | 2479 | 
| 2450 return 0; | 2480 return 0; | 
| 2451 } | 2481 } | 
| 2452 | 2482 | 
| 2453 } // namespace blink | 2483 } // namespace blink | 
| OLD | NEW |