Beging implementing reftests

This commit is contained in:
Niklas von Hertzen
2017-08-09 00:50:31 +08:00
parent 93f08c7547
commit 58d1bef3b6
163 changed files with 15221 additions and 14371 deletions

View File

@ -247,3 +247,5 @@ const NAMED_COLORS = {
yellow: [255, 255, 0, null],
yellowgreen: [154, 205, 50, null]
};
export const TRANSPARENT = new Color([0, 0, 0, 0]);

View File

@ -151,34 +151,48 @@ export default class Renderer {
}
renderNodeBackgroundAndBorders(container: NodeContainer) {
const HAS_BACKGROUND =
!container.style.background.backgroundColor.isTransparent() ||
container.style.background.backgroundImage.length;
const renderableBorders = container.style.border.filter(
border =>
border.borderStyle !== BORDER_STYLE.NONE && !border.borderColor.isTransparent()
);
const callback = () => {
const backgroundPaintingArea = calculateBackgroungPaintingArea(
container.curvedBounds,
container.style.background.backgroundClip
);
this.target.clip([backgroundPaintingArea], () => {
if (!container.style.background.backgroundColor.isTransparent()) {
this.target.fill(container.style.background.backgroundColor);
}
this.renderBackgroundImage(container);
});
if (HAS_BACKGROUND) {
this.target.clip([backgroundPaintingArea], () => {
if (!container.style.background.backgroundColor.isTransparent()) {
this.target.fill(container.style.background.backgroundColor);
}
container.style.border.forEach((border, side) => {
this.renderBackgroundImage(container);
});
}
renderableBorders.forEach((border, side) => {
this.renderBorder(border, side, container.curvedBounds);
});
};
const paths = container.parent ? container.parent.getClipPaths() : [];
if (paths.length) {
this.target.clip(paths, callback);
} else {
callback();
if (HAS_BACKGROUND || renderableBorders.length) {
const paths = container.parent ? container.parent.getClipPaths() : [];
if (paths.length) {
this.target.clip(paths, callback);
} else {
callback();
}
}
}
renderBackgroundImage(container: NodeContainer) {
container.style.background.backgroundImage.reverse().forEach(backgroundImage => {
container.style.background.backgroundImage.slice(0).reverse().forEach(backgroundImage => {
if (backgroundImage.source.method === 'url' && backgroundImage.source.args.length) {
this.renderBackgroundRepeat(container, backgroundImage);
} else {
@ -224,9 +238,7 @@ export default class Renderer {
}
renderBorder(border: Border, side: BorderSide, curvePoints: BoundCurves) {
if (border.borderStyle !== BORDER_STYLE.NONE && !border.borderColor.isTransparent()) {
this.target.drawShape(parsePathForBorder(curvePoints, side), border.borderColor);
}
this.target.drawShape(parsePathForBorder(curvePoints, side), border.borderColor);
}
renderStack(stack: StackingContext) {

View File

@ -10,7 +10,7 @@ import Logger from './Logger';
import ImageLoader from './ImageLoader';
import {Bounds, parseDocumentSize} from './Bounds';
import {cloneWindow} from './Clone';
import Color from './Color';
import Color, {TRANSPARENT} from './Color';
import {FontMetrics} from './Font';
export type Options = {
@ -24,7 +24,9 @@ export type Options = {
target: RenderTarget<*> | Array<RenderTarget<*>>,
type: ?string,
windowWidth: number,
windowHeight: number
windowHeight: number,
offsetX: number,
offsetY: number
};
const html2canvas = (element: HTMLElement, config: Options): Promise<*> => {
@ -47,14 +49,16 @@ const html2canvas = (element: HTMLElement, config: Options): Promise<*> => {
target: new CanvasRenderer(config.canvas),
type: null,
windowWidth: defaultView.innerWidth,
windowHeight: defaultView.innerHeight
windowHeight: defaultView.innerHeight,
offsetX: defaultView.pageXOffset,
offsetY: defaultView.pageYOffset
};
const options = {...defaultOptions, ...config};
const windowBounds = new Bounds(
defaultView.pageXOffset,
defaultView.pageYOffset,
options.offsetX,
options.offsetY,
options.windowWidth,
options.windowHeight
);
@ -91,6 +95,10 @@ const html2canvas = (element: HTMLElement, config: Options): Promise<*> => {
: stack.container.style.background.backgroundColor
: null;
if (backgroundColor === stack.container.style.background.backgroundColor) {
stack.container.style.background.backgroundColor = TRANSPARENT;
}
return imageLoader.ready().then(imageStore => {
if (options.removeContainer === true) {
if (container.parentNode) {

View File

@ -350,11 +350,13 @@ const parseBackgroundImage = (image: string, imageLoader: ImageLoader): Array<Ba
const key = imageLoader.loadImage(args[0]);
args = key ? [key] : [];
}
results.push({
prefix,
method,
args
});
if (method !== 'none') {
results.push({
prefix,
method,
args
});
}
}
args = [];
method = definition = '';

View File

@ -39,7 +39,7 @@ export const parseBorder = (style: CSSStyleDeclaration): Array<Border> => {
return SIDES.map(side => {
const borderColor = new Color(style.getPropertyValue(`border-${side}-color`));
const borderStyle = parseBorderStyle(style.getPropertyValue(`border-${side}-style`));
const borderWidth = parseInt(style.getPropertyValue(`border-${side}-width`), 10);
const borderWidth = parseFloat(style.getPropertyValue(`border-${side}-width`));
return {
borderColor,
borderStyle,

View File

@ -1,5 +1,6 @@
/* @flow */
'use strict';
import {parse} from 'url';
import type {RenderTarget, RenderOptions} from '../Renderer';
import type Color from '../Color';
@ -33,10 +34,11 @@ class RefTestRenderer implements RenderTarget<string> {
this.indent = 0;
this.lines = [];
options.logger.log(`RefTest renderer initialized`);
this.writeLine(`Window: [${options.width}, ${options.height}]`);
}
clip(clipPaths: Array<Path>, callback: () => void) {
this.writeLine(`Clip ${clipPaths.map(this.formatPath, this).join(', ')}`);
this.writeLine(`Clip: ${clipPaths.map(this.formatPath, this).join(' | ')}`);
this.indent += 2;
callback();
this.indent -= 2;
@ -44,18 +46,18 @@ class RefTestRenderer implements RenderTarget<string> {
drawImage(image: ImageElement, source: Bounds, destination: Bounds) {
this.writeLine(
`Draw image ${this.formatImage(image)} (source: ${this.formatBounds(
`Draw image: ${this.formatImage(image)} (source: ${this.formatBounds(
source
)} (destination: ${this.formatBounds(source)})`
)}) (destination: ${this.formatBounds(source)})`
);
}
drawShape(path: Path, color: Color) {
this.writeLine(`Shape ${color.toString()} ${this.formatPath(path)}`);
this.writeLine(`Shape: ${color.toString()} ${this.formatPath(path)}`);
}
fill(color: Color) {
this.writeLine(`Fill ${color.toString()}`);
this.writeLine(`Fill: ${color.toString()}`);
}
getTarget(): Promise<string> {
@ -64,7 +66,7 @@ class RefTestRenderer implements RenderTarget<string> {
rectangle(x: number, y: number, width: number, height: number, color: Color) {
const list = [x, y, width, height].map(v => Math.round(v)).join(', ');
this.writeLine(`Rectangle [${list}] ${color.toString()}`);
this.writeLine(`Rectangle: [${list}] ${color.toString()}`);
}
formatBounds(bounds: Bounds): string {
@ -73,8 +75,10 @@ class RefTestRenderer implements RenderTarget<string> {
}
formatImage(image: ImageElement): string {
// $FlowFixMe
return image.tagName === 'CANVAS' ? 'Canvas' : `Image src="${image.src}"`;
return image.tagName === 'CANVAS'
? 'Canvas'
: // $FlowFixMe
`Image ("${parse(image.src).pathname.substring(0, 100)}")`;
}
formatPath(path: Path): string {
@ -86,7 +90,7 @@ class RefTestRenderer implements RenderTarget<string> {
const string = path
.map(v => {
if (v.type === PATH.VECTOR) {
return `Vector(x: ${Math.round(v.x)}, y: ${Math.round(v.y)}))`;
return `Vector(x: ${Math.round(v.x)}, y: ${Math.round(v.y)})`;
}
if (v.type === PATH.BEZIER_CURVE) {
const values = [
@ -102,7 +106,7 @@ class RefTestRenderer implements RenderTarget<string> {
return `BezierCurve(${values.join(', ')})`;
}
})
.join(', ');
.join(' > ');
return `Path (${string})`;
}
@ -114,12 +118,14 @@ class RefTestRenderer implements RenderTarget<string> {
`y1: ${Math.round(gradient.direction.y1)}`
];
const stops = gradient.colorStops.map(stop => `${stop.color.toString()} ${stop.stop}px`);
const stops = gradient.colorStops.map(
stop => `${stop.color.toString()} ${Math.round(stop.stop * 100) / 100}`
);
this.writeLine(
`${this.formatBounds(bounds)} linear-gradient(${direction.join(', ')} ${stops.join(
`Gradient: ${this.formatBounds(bounds)} linear-gradient(${direction.join(
', '
)})`
)} ${stops.join(', ')})`
);
}
@ -131,7 +137,7 @@ class RefTestRenderer implements RenderTarget<string> {
offsetY: number
) {
this.writeLine(
`Repeat ${this.formatImage(
`Repeat: ${this.formatImage(
image
)} [${offsetX}, ${offsetY}] Size (${imageSize.width}, ${imageSize.height}) ${this.formatPath(
path
@ -151,7 +157,7 @@ class RefTestRenderer implements RenderTarget<string> {
font.fontVariant,
font.fontWeight,
font.fontSize,
font.fontFamily
font.fontFamily.replace(/"/g, '')
]
.join(' ')
.split(',')[0];
@ -167,7 +173,7 @@ class RefTestRenderer implements RenderTarget<string> {
: '';
this.writeLine(
`Text ${color.toString()} ${fontString}${shadowString}${textDecorationString}`
`Text: ${color.toString()} ${fontString}${shadowString}${textDecorationString}`
);
this.indent += 2;
@ -231,18 +237,22 @@ class RefTestRenderer implements RenderTarget<string> {
}
setOpacity(opacity: number) {
this.writeLine(`Opacity ${opacity}`);
this.writeLine(`Opacity: ${opacity}`);
}
transform(offsetX: number, offsetY: number, matrix: Matrix, callback: () => void) {
this.writeLine(`Transform (${offsetX}, ${offsetY}) [${matrix.join(', ')}]`);
this.writeLine(
`Transform: (${Math.round(offsetX)}, ${Math.round(offsetY)}) [${matrix
.map(v => Math.round(v * 100) / 100)
.join(', ')}]`
);
this.indent += 2;
callback();
this.indent -= 2;
}
writeLine(text: string) {
this.lines.push(`${new Array(this.indent).join(' ')}${text}`);
this.lines.push(`${new Array(this.indent + 1).join(' ')}${text}`);
}
}