From 99390d2d8800628b7d4aa602ec1951c74259b07e Mon Sep 17 00:00:00 2001 From: ppchart Date: Mon, 17 Oct 2022 15:20:39 +0800 Subject: [PATCH] fix: Some svg image sizes are drawn incorrectly --- src/render/canvas/canvas-renderer.ts | 103 ++++++++++------------ tests/reftests/images/svg/background.html | 42 +++++++++ tests/reftests/images/svg/base64.html | 15 +++- 3 files changed, 101 insertions(+), 59 deletions(-) create mode 100644 tests/reftests/images/svg/background.html diff --git a/src/render/canvas/canvas-renderer.ts b/src/render/canvas/canvas-renderer.ts index 6efb648bf..43e8b460f 100644 --- a/src/render/canvas/canvas-renderer.ts +++ b/src/render/canvas/canvas-renderer.ts @@ -1,49 +1,49 @@ -import {ElementPaint, parseStackingContexts, StackingContext} from '../stacking-context'; -import {asString, Color, isTransparent} from '../../css/types/color'; -import {ElementContainer, FLAGS} from '../../dom/element-container'; -import {BORDER_STYLE} from '../../css/property-descriptors/border-style'; -import {CSSParsedDeclaration} from '../../css'; -import {TextContainer} from '../../dom/text-container'; -import {Path, transformPath} from '../path'; -import {BACKGROUND_CLIP} from '../../css/property-descriptors/background-clip'; -import {BoundCurves, calculateBorderBoxPath, calculateContentBoxPath, calculatePaddingBoxPath} from '../bound-curves'; -import {BezierCurve, isBezierCurve} from '../bezier-curve'; -import {Vector} from '../vector'; -import {CSSImageType, CSSURLImage, isLinearGradient, isRadialGradient} from '../../css/types/image'; +import { ElementPaint, parseStackingContexts, StackingContext } from '../stacking-context'; +import { asString, Color, isTransparent } from '../../css/types/color'; +import { ElementContainer, FLAGS } from '../../dom/element-container'; +import { BORDER_STYLE } from '../../css/property-descriptors/border-style'; +import { CSSParsedDeclaration } from '../../css'; +import { TextContainer } from '../../dom/text-container'; +import { Path, transformPath } from '../path'; +import { BACKGROUND_CLIP } from '../../css/property-descriptors/background-clip'; +import { BoundCurves, calculateBorderBoxPath, calculateContentBoxPath, calculatePaddingBoxPath } from '../bound-curves'; +import { BezierCurve, isBezierCurve } from '../bezier-curve'; +import { Vector } from '../vector'; +import { CSSImageType, CSSURLImage, isLinearGradient, isRadialGradient } from '../../css/types/image'; import { parsePathForBorder, parsePathForBorderDoubleInner, parsePathForBorderDoubleOuter, parsePathForBorderStroke } from '../border'; -import {calculateBackgroundRendering, getBackgroundValueForIndex} from '../background'; -import {isDimensionToken} from '../../css/syntax/parser'; -import {segmentGraphemes, TextBounds} from '../../css/layout/text'; -import {ImageElementContainer} from '../../dom/replaced-elements/image-element-container'; -import {contentBox} from '../box-sizing'; -import {CanvasElementContainer} from '../../dom/replaced-elements/canvas-element-container'; -import {SVGElementContainer} from '../../dom/replaced-elements/svg-element-container'; -import {ReplacedElementContainer} from '../../dom/replaced-elements'; -import {EffectTarget, IElementEffect, isClipEffect, isOpacityEffect, isTransformEffect} from '../effects'; -import {contains} from '../../core/bitwise'; -import {calculateGradientDirection, calculateRadius, processColorStops} from '../../css/types/functions/gradient'; -import {FIFTY_PERCENT, getAbsoluteValue} from '../../css/types/length-percentage'; -import {TEXT_DECORATION_LINE} from '../../css/property-descriptors/text-decoration-line'; -import {FontMetrics} from '../font-metrics'; -import {DISPLAY} from '../../css/property-descriptors/display'; -import {Bounds} from '../../css/layout/bounds'; -import {LIST_STYLE_TYPE} from '../../css/property-descriptors/list-style-type'; -import {computeLineHeight} from '../../css/property-descriptors/line-height'; -import {CHECKBOX, INPUT_COLOR, InputElementContainer, RADIO} from '../../dom/replaced-elements/input-element-container'; -import {TEXT_ALIGN} from '../../css/property-descriptors/text-align'; -import {TextareaElementContainer} from '../../dom/elements/textarea-element-container'; -import {SelectElementContainer} from '../../dom/elements/select-element-container'; -import {IFrameElementContainer} from '../../dom/replaced-elements/iframe-element-container'; -import {TextShadow} from '../../css/property-descriptors/text-shadow'; -import {PAINT_ORDER_LAYER} from '../../css/property-descriptors/paint-order'; -import {Renderer} from '../renderer'; -import {Context} from '../../core/context'; -import {DIRECTION} from '../../css/property-descriptors/direction'; +import { calculateBackgroundRendering, getBackgroundValueForIndex } from '../background'; +import { isDimensionToken } from '../../css/syntax/parser'; +import { segmentGraphemes, TextBounds } from '../../css/layout/text'; +import { ImageElementContainer } from '../../dom/replaced-elements/image-element-container'; +import { contentBox } from '../box-sizing'; +import { CanvasElementContainer } from '../../dom/replaced-elements/canvas-element-container'; +import { SVGElementContainer } from '../../dom/replaced-elements/svg-element-container'; +import { ReplacedElementContainer } from '../../dom/replaced-elements'; +import { EffectTarget, IElementEffect, isClipEffect, isOpacityEffect, isTransformEffect } from '../effects'; +import { contains } from '../../core/bitwise'; +import { calculateGradientDirection, calculateRadius, processColorStops } from '../../css/types/functions/gradient'; +import { FIFTY_PERCENT, getAbsoluteValue } from '../../css/types/length-percentage'; +import { TEXT_DECORATION_LINE } from '../../css/property-descriptors/text-decoration-line'; +import { FontMetrics } from '../font-metrics'; +import { DISPLAY } from '../../css/property-descriptors/display'; +import { Bounds } from '../../css/layout/bounds'; +import { LIST_STYLE_TYPE } from '../../css/property-descriptors/list-style-type'; +import { computeLineHeight } from '../../css/property-descriptors/line-height'; +import { CHECKBOX, INPUT_COLOR, InputElementContainer, RADIO } from '../../dom/replaced-elements/input-element-container'; +import { TEXT_ALIGN } from '../../css/property-descriptors/text-align'; +import { TextareaElementContainer } from '../../dom/elements/textarea-element-container'; +import { SelectElementContainer } from '../../dom/elements/select-element-container'; +import { IFrameElementContainer } from '../../dom/replaced-elements/iframe-element-container'; +import { TextShadow } from '../../css/property-descriptors/text-shadow'; +import { PAINT_ORDER_LAYER } from '../../css/property-descriptors/paint-order'; +import { Renderer } from '../renderer'; +import { Context } from '../../core/context'; +import { DIRECTION } from '../../css/property-descriptors/direction'; export type RenderConfigurations = RenderOptions & { backgroundColor: Color | null; @@ -181,7 +181,7 @@ export class CanvasRenderer extends Renderer { this.ctx.direction = styles.direction === DIRECTION.RTL ? 'rtl' : 'ltr'; this.ctx.textAlign = 'left'; this.ctx.textBaseline = 'alphabetic'; - const {baseline, middle} = this.fontMetrics.getMetrics(fontFamily, fontSize); + const { baseline, middle } = this.fontMetrics.getMetrics(fontFamily, fontSize); const paintOrder = styles.paintOrder; text.textBounds.forEach((text) => { @@ -278,10 +278,6 @@ export class CanvasRenderer extends Renderer { this.ctx.clip(); this.ctx.drawImage( image, - 0, - 0, - container.intrinsicWidth, - container.intrinsicHeight, box.left, box.top, box.width, @@ -389,7 +385,7 @@ export class CanvasRenderer extends Renderer { if (isTextInputElement(container) && container.value.length) { const [fontFamily, fontSize] = this.createFontStyle(styles); - const {baseline} = this.fontMetrics.getMetrics(fontFamily, fontSize); + const { baseline } = this.fontMetrics.getMetrics(fontFamily, fontSize); this.ctx.font = fontFamily; this.ctx.fillStyle = asString(styles.color); @@ -569,16 +565,13 @@ export class CanvasRenderer extends Renderer { } resizeImage(image: HTMLImageElement, width: number, height: number): HTMLCanvasElement | HTMLImageElement { - if (image.width === width && image.height === height) { - return image; - } - const ownerDocument = this.canvas.ownerDocument ?? document; const canvas = ownerDocument.createElement('canvas'); canvas.width = Math.max(1, width); canvas.height = Math.max(1, height); const ctx = canvas.getContext('2d') as CanvasRenderingContext2D; - ctx.drawImage(image, 0, 0, image.width, image.height, 0, 0, width, height); + ctx.scale(width / image.width, height / image.height) + ctx.drawImage(image, 0, 0, image.width, image.height); return canvas; } @@ -696,10 +689,10 @@ export class CanvasRenderer extends Renderer { const hasBackground = !isTransparent(styles.backgroundColor) || styles.backgroundImage.length; const borders = [ - {style: styles.borderTopStyle, color: styles.borderTopColor, width: styles.borderTopWidth}, - {style: styles.borderRightStyle, color: styles.borderRightColor, width: styles.borderRightWidth}, - {style: styles.borderBottomStyle, color: styles.borderBottomColor, width: styles.borderBottomWidth}, - {style: styles.borderLeftStyle, color: styles.borderLeftColor, width: styles.borderLeftWidth} + { style: styles.borderTopStyle, color: styles.borderTopColor, width: styles.borderTopWidth }, + { style: styles.borderRightStyle, color: styles.borderRightColor, width: styles.borderRightWidth }, + { style: styles.borderBottomStyle, color: styles.borderBottomColor, width: styles.borderBottomWidth }, + { style: styles.borderLeftStyle, color: styles.borderLeftColor, width: styles.borderLeftWidth } ]; const backgroundPaintingArea = calculateBackgroundCurvedPaintingArea( diff --git a/tests/reftests/images/svg/background.html b/tests/reftests/images/svg/background.html new file mode 100644 index 000000000..88cb1a88c --- /dev/null +++ b/tests/reftests/images/svg/background.html @@ -0,0 +1,42 @@ + + + + + Base64 svg + + + + + + +
+ Inline svg1 image(same size as fixed size):
+
+ + Inline svg2 image(custom size):
+
+
+ + + \ No newline at end of file diff --git a/tests/reftests/images/svg/base64.html b/tests/reftests/images/svg/base64.html index c8f9af6f2..f9036fd2f 100644 --- a/tests/reftests/images/svg/base64.html +++ b/tests/reftests/images/svg/base64.html @@ -1,5 +1,6 @@ + Base64 svg @@ -10,9 +11,15 @@ } + -
- Inline svg image:
-
+
+ Inline svg image:
+ + +
- + + \ No newline at end of file