for (let i = 0; i < input.length; i++) { const rawItem = input[i]; if (rawItem.defaultAttr.ignore) { continue; }
const label = rawItem.label; const transform = label.getComputedTransform(); // NOTE: Get bounding rect after getComputedTransform, or label may not been updated by the host el. // 这里获取了label的外层包围盒 const localRect = label.getBoundingRect(); const isAxisAligned = !transform || (transform[1] < 1e-5 && transform[2] < 1e-5);
getBoundingRect(): BoundingRect { if (this.styleChanged()) { this._updateSubTexts(); } if (!this._rect) { // TODO: Optimize when using width and overflow: wrap/truncate const tmpRect = newBoundingRect(0, 0, 0, 0); const children = this._children; consttmpMat: MatrixArray = []; let rect = null;
for (let i = 0; i < children.length; i++) { const child = children[i]; const childRect = child.getBoundingRect(); const transform = child.getLocalTransform(tmpMat);
if (transform) { tmpRect.copy(childRect); tmpRect.applyTransform(transform); rect = rect || tmpRect.clone(); rect.union(tmpRect); } else { rect = rect || childRect.clone(); rect.union(childRect); } } this._rect = rect || tmpRect; } returnthis._rect; }
// `textBaseline` is set as 'middle'. textY += lineHeight / 2;
if (textPadding) { textX = getTextXForPadding(baseX, textAlign, textPadding); if (verticalAlign === 'top') { textY += textPadding[0]; } elseif (verticalAlign === 'bottom') { textY -= textPadding[2]; } }
let defaultLineWidth = 0; let useDefaultFill = false; const textFill = getFill( 'fill'in style ? style.fill : (useDefaultFill = true, defaultStyle.fill) ); const textStroke = getStroke( 'stroke'in style ? style.stroke : (!bgColorDrawn // If we use "auto lineWidth" widely, it probably bring about some bad case. // So the current strategy is: // If `style.fill` is specified (i.e., `useDefaultFill` is `false`) // (A) And if `textConfig.insideStroke/outsideStroke` is not specified as a color // (i.e., `defaultStyle.autoStroke` is `true`), we do not actually display // the auto stroke because we can not make sure wether the stoke is approperiate to // the given `fill`. // (B) But if `textConfig.insideStroke/outsideStroke` is specified as a color, // we give the auto lineWidth to display the given stoke color. && (!defaultStyle.autoStroke || useDefaultFill) ) ? (defaultLineWidth = DEFAULT_STROKE_LINE_WIDTH, defaultStyle.stroke) : null );
for (let i = 0; i < textLines.length; i++) { const el = this._getOrCreateChild(TSpan); // Always create new style. constsubElStyle: TSpanStyleProps = el.createStyle(); el.useStyle(subElStyle); subElStyle.text = textLines[i]; subElStyle.x = textX; subElStyle.y = textY; // Always set textAlign and textBase line, because it is difficute to calculate // textAlign from prevEl, and we dont sure whether textAlign will be reset if // font set happened. if (textAlign) { subElStyle.textAlign = textAlign; } // Force baseline to be "middle". Otherwise, if using "top", the // text will offset downward a little bit in font "Microsoft YaHei". subElStyle.textBaseline = 'middle'; subElStyle.opacity = style.opacity; // Fill after stroke so the outline will not cover the main part. subElStyle.strokeFirst = true;
if (fixedBoundingRect) { el.setBoundingRect(newBoundingRect( adjustTextX(subElStyle.x, style.width, subElStyle.textAlignasTextAlign), adjustTextY(subElStyle.y, calculatedLineHeight, subElStyle.textBaselineasTextVerticalAlign), /** * Text boundary should be the real text width. * Otherwise, there will be extra space in the * bounding rect calculated. */ contentWidth, calculatedLineHeight )); } } }
staticmakeFont(style: TextStylePropsPart): string { // FIXME in node-canvas fontWeight is before fontStyle // Use `fontSize` `fontFamily` to check whether font properties are defined. let font = ''; if (hasSeparateFont(style)) { font = [ style.fontStyle, style.fontWeight, parseFontSize(style.fontSize), // If font properties are defined, `fontFamily` should not be ignored. style.fontFamily || 'sans-serif' ].join(' '); } return font && trim(font) || style.textFont || style.font; } }
// 这里在创建圆角矩形的path exportfunctionbuildPath(ctx: CanvasRenderingContext2D | PathProxy, shape: { x: number y: number width: number height: number r?: number | number[] }) { let x = shape.x; let y = shape.y; let width = shape.width; let height = shape.height; let r = shape.r; let r1; let r2; let r3; let r4;
// Convert width and height to positive for better borderRadius if (width < 0) { x = x + width; width = -width; } if (height < 0) { y = y + height; height = -height; }