Skip to content

Commit 18847fd

Browse files
committed
DVF-2707-chart-axes-drawing-algorithm-optimization
1 parent 69ca295 commit 18847fd

File tree

6 files changed

+134
-28
lines changed

6 files changed

+134
-28
lines changed

src/vector/Element.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,11 +1027,12 @@ acgraph.vector.Element.prototype.getTransformationMatrix = function() {
10271027
* This method must be overloaded if you need more than one DOM operation to creat a DOM element.
10281028
* Even if you only want to define which DOM must be used - you need to overload.
10291029
* {@link acgraph.vector.Element#createDomInternal}.
1030+
* @param {boolean=} opt_force .
10301031
* @protected
10311032
*/
1032-
acgraph.vector.Element.prototype.createDom = function() {
1033+
acgraph.vector.Element.prototype.createDom = function(opt_force) {
10331034
var stage = this.getStage();
1034-
if (stage && stage.acquireDomChange(acgraph.vector.Stage.DomChangeType.ELEMENT_CREATE)) {
1035+
if (stage && stage.acquireDomChange(acgraph.vector.Stage.DomChangeType.ELEMENT_CREATE) || opt_force) {
10351036
this.domElement_ = this.createDomInternal();
10361037
acgraph.register(this);
10371038
this.clearDirtyState(acgraph.vector.Element.DirtyState.DOM_MISSING);

src/vector/Renderer.js

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,9 +68,8 @@ acgraph.vector.Renderer.prototype.getEmptyStringBounds = function(style) {
6868
* Returns simple hash of a passed style object.
6969
* @param {Object} value Style object.
7070
* @return {string} Hash of a style object.
71-
* @private
7271
*/
73-
acgraph.vector.Renderer.prototype.getStyleHash_ = function(value) {
72+
acgraph.vector.Renderer.prototype.getStyleHash = function(value) {
7473
var hash = '';
7574
for (var j = 0, l = this.settingsAffectingSize.length; j < l; j++) {
7675
var prop = value[this.settingsAffectingSize[j]];
@@ -92,7 +91,7 @@ acgraph.vector.Renderer.prototype.getStyleHash_ = function(value) {
9291
*/
9392
acgraph.vector.Renderer.prototype.textBounds = function(text, style, opt_bounds) {
9493
var boundsCache = this.textBoundsCache;
95-
var styleHash = this.getStyleHash_(style);
94+
var styleHash = this.getStyleHash(style);
9695
var styleCache = boundsCache[styleHash];
9796
if (!styleCache) styleCache = boundsCache[styleHash] = {};
9897
var textBoundsCache = styleCache[text];
@@ -103,6 +102,18 @@ acgraph.vector.Renderer.prototype.textBounds = function(text, style, opt_bounds)
103102
};
104103

105104

105+
/**
106+
* Measure DOM text element.
107+
* @param {Element} element .
108+
* @param {string} text .
109+
* @param {Object} style .
110+
* @return {goog.math.Rect} .
111+
*/
112+
acgraph.vector.Renderer.prototype.getBBox = function(element, text, style) {
113+
return this.textBounds(text, style);
114+
};
115+
116+
106117
/**
107118
* Whether the cache contains bounds of passed text and style.
108119
* @param {string} text .
@@ -111,7 +122,7 @@ acgraph.vector.Renderer.prototype.textBounds = function(text, style, opt_bounds)
111122
*/
112123
acgraph.vector.Renderer.prototype.isInBoundsCache = function(text, style) {
113124
var boundsCache = this.textBoundsCache;
114-
var styleHash = this.getStyleHash_(style);
125+
var styleHash = this.getStyleHash(style);
115126
var styleCache = boundsCache[styleHash];
116127

117128
return !!(styleCache && styleCache[text]);

src/vector/Stage.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ acgraph.vector.Stage = function(opt_container, opt_width, opt_height) {
121121
this.rootLayer_ = new acgraph.vector.Layer();
122122
this.rootLayer_.setParent(this).render();
123123
acgraph.getRenderer().appendChild(this.domElement_, this.rootLayer_.domElement());
124+
acgraph.getRenderer().createMeasurement();
124125

125126
this.eventHandler_.listen(this.domElement(), [
126127
goog.events.EventType.MOUSEDOWN,

src/vector/Text.js

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -778,7 +778,23 @@ acgraph.vector.Text.prototype.selectable = function(opt_value) {
778778
*/
779779
acgraph.vector.Text.prototype.style = function(opt_value) {
780780
if (goog.isDefAndNotNull(opt_value)) {
781-
if (opt_value) goog.object.extend(this.style_, opt_value);
781+
782+
goog.object.forEach(opt_value, function(value, key) {
783+
var styleName = key;
784+
switch (key) {
785+
case 'fontDecoration':
786+
case 'textDecoration':
787+
styleName = 'decoration';
788+
break;
789+
case 'fontColor':
790+
styleName = 'color';
791+
break;
792+
case 'fontOpacity':
793+
styleName = 'opacity';
794+
break;
795+
}
796+
this.style_[styleName] = value;
797+
}, this);
782798

783799
this.width_ = parseFloat(this.style_['width']) || 0;
784800
this.height_ = parseFloat(this.style_['height']) || 0;
@@ -1298,7 +1314,7 @@ acgraph.vector.Text.prototype.addSegment = function(text, opt_style) {
12981314
var shift = this.segments_.length == 0 ? this.textIndent_ : 0;
12991315

13001316
// If text width and textWrap are set - start putting a segement into the given bounds.
1301-
if (this.style_['width']) {
1317+
if (goog.isDefAndNotNull(this.style_['width'])) {
13021318
// if a new segment, with all segment already in place and offsets, doesnt' fit:
13031319
// cut characters.
13041320

@@ -1505,7 +1521,7 @@ acgraph.vector.Text.prototype.calculateY = function() {
15051521
acgraph.vector.Text.prototype.textDefragmentation = function() {
15061522
this.init_();
15071523

1508-
var text, i;
1524+
var text, i, segment;
15091525
if (this.text_ == null) return;
15101526

15111527
if (this.htmlOn_) {
@@ -1515,22 +1531,58 @@ acgraph.vector.Text.prototype.textDefragmentation = function() {
15151531
this.text_ = goog.string.canonicalizeNewlines(goog.string.normalizeSpaces(this.text_));
15161532
var textArr = this.text_.split(q);
15171533

1518-
for (i = 0; i < textArr.length; i++) {
1519-
text = textArr[i];
1520-
if (goog.isDefAndNotNull(text)) {
1521-
if (text == '') {
1522-
this.addBreak();
1523-
} else {
1524-
this.addSegment(text);
1525-
this.addBreak();
1534+
if (textArr.length == 1 && !goog.isDefAndNotNull(this.style_['width'])) {
1535+
if (!this.domElement()) {
1536+
this.createDom(true);
1537+
}
1538+
if (this.hasDirtyState(acgraph.vector.Element.DirtyState.STYLE))
1539+
this.renderStyle();
1540+
1541+
segment = new acgraph.vector.TextSegment(this.text_, {});
1542+
this.currentLine_.push(segment);
1543+
this.segments_.push(segment);
1544+
segment.parent(this);
1545+
1546+
if (this.hasDirtyState(acgraph.vector.Element.DirtyState.DATA))
1547+
this.renderData();
1548+
1549+
var bounds = acgraph.getRenderer().getBBox(this.domElement(), this.text_, this.style_);
1550+
1551+
segment.baseLine = -bounds.top;
1552+
segment.height = bounds.height;
1553+
segment.width = bounds.width;
1554+
1555+
// calculate line params with newly added segment.
1556+
this.currentLineHeight_ = bounds.height;
1557+
this.currentLineWidth_ = bounds.width + this.textIndent_;
1558+
this.currentBaseLine_ = segment.baseLine;
1559+
this.currentLineEmpty_ = this.text_.length == 0;
1560+
1561+
this.finalizeTextLine();
1562+
this.currentNumberSeqBreaks_++;
1563+
var height = this.currentLine_[0] ? this.currentLine_[0].height : 0;
1564+
this.accumulatedHeight_ += goog.isString(this.lineHeight_) ?
1565+
parseInt(this.lineHeight_, 0) + height :
1566+
this.lineHeight_ * height;
1567+
1568+
} else {
1569+
for (i = 0; i < textArr.length; i++) {
1570+
text = textArr[i];
1571+
if (goog.isDefAndNotNull(text)) {
1572+
if (text == '') {
1573+
this.addBreak();
1574+
} else {
1575+
this.addSegment(text);
1576+
this.addBreak();
1577+
}
15261578
}
15271579
}
15281580
}
15291581
}
15301582

15311583
if (this.textIndent_ && this.textLines_.length > 0) {
15321584
var line = this.textLines_[0];
1533-
var segment = line[0];
1585+
segment = line[0];
15341586
if (this.rtl) {
15351587
if (!this.style_['hAlign'] ||
15361588
this.style_['hAlign'] == acgraph.vector.Text.HAlign.START ||

src/vector/svg/Renderer.js

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,8 @@ acgraph.vector.svg.Renderer.prototype.getAttribute_ = function(el, key) {
162162
//----------------------------------------------------------------------------------------------------------------------
163163
/**
164164
* Desc.
165-
* @private
166165
*/
167-
acgraph.vector.svg.Renderer.prototype.createMeasurement_ = function() {
166+
acgraph.vector.svg.Renderer.prototype.createMeasurement = function() {
168167
this.measurement_ = this.createSVGElement_('svg');
169168
this.measurementText_ = this.createTextElement();
170169
this.measurementTextNode_ = this.createTextNode('');
@@ -173,6 +172,9 @@ acgraph.vector.svg.Renderer.prototype.createMeasurement_ = function() {
173172
goog.dom.appendChild(this.measurement_, this.measurementText_);
174173
goog.dom.appendChild(goog.dom.getDocument().body, this.measurement_);
175174

175+
this.measurementLayerForBBox_ = this.createLayerElement();
176+
goog.dom.appendChild(this.measurement_, this.measurementLayerForBBox_);
177+
176178
//We need set 'display: block' for <svg> element to prevent scrollbar on 100% height of parent container (see DVF-620)
177179
this.setAttributes_(this.measurement_, {'display': 'block', 'width': 0, 'height': 0});
178180

@@ -189,7 +191,7 @@ acgraph.vector.svg.Renderer.prototype.createMeasurement_ = function() {
189191
*/
190192
acgraph.vector.svg.Renderer.prototype.measure = function(text, style) {
191193
//if (text == '') return new goog.math.Rect(0, 0, 0, 0);
192-
if (!this.measurement_) this.createMeasurement_();
194+
if (!this.measurement_) this.createMeasurement();
193195

194196
var spaceWidth = null;
195197
var additionWidth = 0;
@@ -248,13 +250,53 @@ acgraph.vector.svg.Renderer.prototype.measure = function(text, style) {
248250
};
249251

250252

253+
/** @inheritDoc */
254+
acgraph.vector.svg.Renderer.prototype.getBBox = function(element, text, style) {
255+
var boundsCache = this.textBoundsCache;
256+
var styleHash = this.getStyleHash(style);
257+
var styleCache = boundsCache[styleHash];
258+
if (!styleCache) styleCache = boundsCache[styleHash] = {};
259+
var textBoundsCache = styleCache[text];
260+
261+
if (textBoundsCache) {
262+
return textBoundsCache;
263+
} else {
264+
var spaceWidth = null;
265+
var additionWidth = 0;
266+
267+
if (text.length == 0) {
268+
return this.getEmptyStringBounds(style);
269+
}
270+
271+
if (goog.string.isSpace(text)) {
272+
return this.getSpaceBounds(style);
273+
} else {
274+
if (goog.string.startsWith(text, ' '))
275+
additionWidth += spaceWidth = this.getSpaceBounds(style).width;
276+
if (goog.string.endsWith(text, ' '))
277+
additionWidth += spaceWidth || this.getSpaceBounds(style).width;
278+
}
279+
280+
var parentNode = element.parentNode;
281+
282+
this.measurementLayerForBBox_.appendChild(element);
283+
var bbox = element['getBBox']();
284+
if (parentNode) parentNode.appendChild(element);
285+
286+
var x = element.getAttribute('x') || 0;
287+
var y = element.getAttribute('y') || 0;
288+
return styleCache[text] = new goog.math.Rect(bbox.x - x, bbox.y - y, bbox.width + additionWidth, bbox.height);
289+
}
290+
};
291+
292+
251293
/**
252294
* Measure any svg nodes.
253295
* @param {string|Node} element .
254296
* @return {goog.math.Rect} .
255297
*/
256298
acgraph.vector.svg.Renderer.prototype.measureElement = function(element) {
257-
if (!this.measurement_) this.createMeasurement_();
299+
if (!this.measurement_) this.createMeasurement();
258300

259301
if (goog.isString(element)) {
260302
this.measurementGroupNode_.innerHTML = element;

src/vector/vml/Renderer.js

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,8 @@ acgraph.vector.vml.Renderer.prototype.measurementImage_ = null;
232232
//----------------------------------------------------------------------------------------------------------------------
233233
/**
234234
* Desc.
235-
* @private
236235
*/
237-
acgraph.vector.vml.Renderer.prototype.createMeasurement_ = function() {
236+
acgraph.vector.vml.Renderer.prototype.createMeasurement = function() {
238237

239238
//Text bounds
240239

@@ -293,7 +292,7 @@ acgraph.vector.vml.Renderer.prototype.createMeasurement_ = function() {
293292
* @return {goog.math.Rect} Image bounds.
294293
*/
295294
acgraph.vector.vml.Renderer.prototype.measuringImage = function(src) {
296-
if (!this.measurement_) this.createMeasurement_();
295+
if (!this.measurement_) this.createMeasurement();
297296
this.setAttribute_(this.measurementImage_, 'src', src);
298297
return goog.style.getBounds(this.measurementImage_);
299298
};
@@ -307,7 +306,7 @@ acgraph.vector.vml.Renderer.prototype.measuringImage = function(src) {
307306
* @return {goog.math.Rect} Text bounds.
308307
*/
309308
acgraph.vector.vml.Renderer.prototype.measuringSimpleText = function(text, segmentStyle, textStyle) {
310-
if (!this.measurement_) this.createMeasurement_();
309+
if (!this.measurement_) this.createMeasurement();
311310

312311
this.measurementSimpleText_.style.cssText = '';
313312

@@ -350,7 +349,7 @@ acgraph.vector.vml.Renderer.prototype.measuringSimpleText = function(text, segme
350349
*/
351350
acgraph.vector.vml.Renderer.prototype.measure = function(text, style) {
352351
if (text == '') return new goog.math.Rect(0, 0, 0, 0);
353-
if (!this.measurement_) this.createMeasurement_();
352+
if (!this.measurement_) this.createMeasurement();
354353

355354
goog.dom.removeNode(this.measurementVMLTextPath_);
356355
this.measurementVMLTextPath_ = /** @type {Element} */ (this.createTextNode(''));
@@ -437,7 +436,7 @@ acgraph.vector.vml.Renderer.prototype.measure = function(text, style) {
437436
* @return {goog.math.Rect} .
438437
*/
439438
acgraph.vector.vml.Renderer.prototype.measureElement = function(element) {
440-
if (!this.measurement_) this.createMeasurement_();
439+
if (!this.measurement_) this.createMeasurement();
441440

442441
if (goog.isString(element)) {
443442
this.measurementGroupNode_.innerHTML = element;

0 commit comments

Comments
 (0)