Beispiel #1
0
 def browser_previews(self, **kwargs):
     """Use GFR and diffbrowsers to take screenshots of how the fonts
     will look on different browsers. A Browserstack account is
     required."""
     logger.info("Running browser previews")
     if not self._bstack_auth:
         logger.info("Skipping. No Browserstack credentials. "
                     "See https://github.com/googlefonts/"
                     "diffbrowsers#installation on how to add them.")
         return
     out = os.path.join(self.out, "browser_previews")
     mkdir(out)
     browsers_to_test = test_browsers["vf_browsers"]
     font_groups = self.chunkify(
         list([i['filename'] for i in self.instances.values()]), 4)
     name_groups = self.chunkify(list(self.instances.keys()), 4)
     for name_group, font_group in zip(name_groups, font_groups):
         name = "_".join(sorted(name_group))
         diff_browsers = DiffBrowsers(
             auth=self._bstack_auth,
             gfr_instance_url=FontQA.GFR_URL,
             dst_dir=os.path.join(out, name),
             browsers=browsers_to_test,
             gfr_is_local=False,
         )
         diff_browsers.new_session(font_group, font_group)
         diff_browsers.diff_view("waterfall", styles=name_group)
         diff_browsers.diff_view("glyphs_all", styles=name_group, pt=15)
Beispiel #2
0
 def diffbrowsers(self, **kwargs):
     """Test fonts on GFR regression and take screenshots using
     diffbrowsers. A browserstack account is required."""
     logger.info("Running Diffbrowsers")
     if not self._bstack_auth:
         logger.info("Skipping. No Browserstack credentials. "
                     "See https://github.com/googlefonts/"
                     "diffbrowsers#installation on how to add them.")
         return
     dst = os.path.join(self.out, "Diffbrowsers")
     mkdir(dst)
     browsers_to_test = test_browsers["vf_browsers"]
     fonts = [(k, self.instances_before[k]['filename'],
               self.instances[k]['filename'])
              for k in self.matching_instances]
     font_groups = self.chunkify(sorted(fonts), 4)
     for group in font_groups:
         styles = [i[0] for i in group]
         dir_name = "_".join(styles)
         fonts_before = [i[1] for i in group]
         fonts_after = [i[2] for i in group]
         out = os.path.join(dst, dir_name)
         diff_browsers = DiffBrowsers(
             auth=self._bstack_auth,
             gfr_instance_url=self.GFR_URL,
             dst_dir=out,
             browsers=browsers_to_test,
         )
         diff_browsers.new_session(set(fonts_before), set(fonts_after))
         diff_browsers.diff_view("waterfall", styles=styles)
         info = os.path.join(out, "info.json")
         json.dump(diff_browsers.stats, open(info, "w"))
         diff_browsers.diff_view("glyphs_all", pt=16, styles=styles)
Beispiel #3
0
    def diffenator(self, **kwargs):
        logger.info("Running Diffenator")
        dst = os.path.join(self._out, "Diffenator")
        mkdir(dst)
        for style in self._shared_instances:
            font_before = DFont(self._instances_before[style])
            font_after = DFont(self._instances[style])
            out = os.path.join(dst, style)
            if font_after.is_variable and not font_before.is_variable:
                font_after.set_variations_from_static(font_before)

            elif not font_after.is_variable and font_before.is_variable:
                font_before.set_variations_from_static(font_after)

            elif font_after.is_variable and font_before.is_variable:
                # TODO get wdth and slnt axis vals
                variations = {"wght": font_before.ttfont["OS/2"].usWeightClass}
                font_after.set_variations(variations)
                font_before.set_variations(variations)

            # TODO add settings
            diff = DiffFonts(font_before, font_after, {"render_diffs": True})
            diff.to_gifs(dst=out)
            diff.to_txt(20, os.path.join(out, "report.txt"))
            diff.to_md(20, os.path.join(out, "report.md"))
            diff.to_html(20, os.path.join(out, "report.html"), image_dir=".")
Beispiel #4
0
    def diffenator(self, **kwargs):
        logger.info("Running Diffenator")
        dst = os.path.join(self.out, "Diffenator")
        mkdir(dst)
        for style in self.matching_instances:
            font_before = DFont(self.instances_before[style]['filename'])
            font_after = DFont(self.instances[style]['filename'])
            out = os.path.join(dst, style)
            if font_after.is_variable and not font_before.is_variable:
                font_after.set_variations_from_static(font_before)

            elif not font_after.is_variable and font_before.is_variable:
                font_before.set_variations_from_static(font_after)

            elif font_after.is_variable and font_before.is_variable:
                coordinates = self.instances_before[style]['coordinates']
                font_after.set_variations(coordinates)
                font_before.set_variations(coordinates)

            # TODO add settings
            diff = DiffFonts(font_before, font_after, {"render_diffs": True})
            diff.to_gifs(dst=out)
            diff.to_txt(20, os.path.join(out, "report.txt"))
            diff.to_md(20, os.path.join(out, "report.md"))
            diff.to_html(20, os.path.join(out, "report.html"), image_dir=".")
Beispiel #5
0
 def fontbakery(self):
     logger.info("Running Fontbakery")
     out = os.path.join(self.out, "Fontbakery")
     mkdir(out)
     cmd = (["fontbakery", "check-googlefonts", "-l", "WARN"] +
            [f.reader.file.name for f in self.fonts] + ["-C"] +
            ["--ghmarkdown", os.path.join(out, "report.md")])
     subprocess.call(cmd)
Beispiel #6
0
 def __init__(self, fonts, fonts_before=None, out="out"):
     self._fonts = fonts
     self._instances = self.font_instances(self._fonts)
     self._fonts_before = fonts_before
     self._instances_before = self.font_instances(self._fonts_before)
     self._shared_instances = self._get_shared_instances()
     self._bstack_auth = load_browserstack_credentials()
     self._out = out
     mkdir(self._out)
Beispiel #7
0
 def browser_previews(self, **kwargs):
     """Use GFR and diffbrowsers to take screenshots of how the fonts
     will look on different browsers. A Browserstack account is
     required."""
     logger.info("Running browser previews")
     if not self._bstack_auth:
         logger.info("Skipping. No Browserstack credentials. "
                     "See https://github.com/googlefonts/"
                     "diffbrowsers#installation on how to add them.")
         return
     out = os.path.join(self.out, "browser_previews")
     mkdir(out)
     html = HtmlProof(out=out,
                      fonts=[f.reader.file.name for f in self.fonts])
     html.build_pages(["waterfall.html", "text.html"])
     html.build_pages(["glyphs.html"], pt_size=16)
     html.save_imgs()
Beispiel #8
0
 def plot_glyphs(self):
     logger.info("Running plot glyphs")
     out = os.path.join(self.out, "plot_glyphs")
     mkdir(out)
     fonts = [f.reader.file.name for f in self.fonts]
     for font in fonts:
         font_filename = os.path.basename(font)[:-4]
         dfont = DFont(font)
         if dfont.is_variable:
             for _, coords in dfont.instances_coordinates.items():
                 dfont.set_variations(coords)
                 img_out = os.path.join(
                     out,
                     "%s_%s.png"
                     % (font_filename, self._instance_coords_to_filename(coords)),
                 )
                 dfont.glyphs.to_png(img_out, limit=100000)
         else:
             img_out = os.path.join(out, font_filename + ".png")
             dfont.glyphs.to_png(dst=img_out)
Beispiel #9
0
    def diffbrowsers(self, **kwargs):
        """Test fonts on GFR regression and take screenshots using
        diffbrowsers. A browserstack account is required."""
        logger.info("Running Diffbrowsers")
        if not self._bstack_auth:
            logger.info("Skipping. No Browserstack credentials. "
                        "See https://github.com/googlefonts/"
                        "diffbrowsers#installation on how to add them.")
            return
        dst = os.path.join(self.out, "Diffbrowsers")
        mkdir(dst)

        html = HtmlDiff(
            out=dst,
            fonts_before=[f.reader.file.name for f in self.fonts_before],
            fonts_after=[f.reader.file.name for f in self.fonts],
        )
        html.build_pages(["waterfall.html", "text.html"])
        html.build_pages(["glyphs.html"], pt_size=16)
        html.save_imgs()
Beispiel #10
0
 def diffbrowsers(self, **kwargs):
     """Test fonts on GFR regression and take screenshots using
     diffbrowsers. A browserstack account is required."""
     logger.info("Running Diffbrowsers")
     if not self._bstack_auth:
         logger.info("Skipping. No Browserstack credentials. "
                 "See https://github.com/googlefonts/"
                 "diffbrowsers#installation on how to add them.")
         return
     dst = os.path.join(self._out, "Diffbrowsers")
     mkdir(dst)
     browsers_to_test = test_browsers["vf_browsers"]
     fonts = sorted(
         [v for k, v in self._instances.items() if k in self._shared_instances]
     )
     fonts_before = sorted(
         [
             v
             for k, v in self._instances_before.items()
             if k in self._shared_instances
         ]
     )
     fonts_before_groups = self.chunkify(fonts_before, 4)
     fonts_groups = self.chunkify(fonts, 4)
     name_groups = self.chunkify(sorted([k for k in self._shared_instances]), 4)
     for name_group, before, after in zip(name_groups, fonts_before_groups, fonts_groups):
         name = "_".join(name_group)
         out = os.path.join(dst, name)
         diff_browsers = DiffBrowsers(
             auth=self._bstack_auth,
             gfr_instance_url=self.GFR_URL,
             dst_dir=out,
             browsers=browsers_to_test,
         )
         diff_browsers.new_session(set(before), set(after))
         diff_browsers.diff_view("waterfall")
         info = os.path.join(out, "info.json")
         json.dump(diff_browsers.stats, open(info, "w"))
         diff_browsers.diff_view("glyphs_all", pt=16)
Beispiel #11
0
def main():
    parser = argparse.ArgumentParser(
        description=__doc__,
        formatter_class=argparse.RawDescriptionHelpFormatter)

    font_group = parser.add_argument_group(title="Fonts to qa")
    font_input_group = font_group.add_mutually_exclusive_group(required=True)
    font_input_group.add_argument("-f",
                                  "--fonts",
                                  nargs="+",
                                  help="Paths to fonts")
    font_input_group.add_argument("-pr",
                                  "--pull-request",
                                  help="Get fonts from a Github pull request")
    font_input_group.add_argument("-gh",
                                  "--github-dir",
                                  help="Get fonts from a Github directory")
    font_input_group.add_argument("-gf",
                                  "--googlefonts",
                                  help="Get fonts from Google Fonts")

    font_before_group = parser.add_argument_group(title="Fonts before input")
    font_before_input_group = font_before_group.add_mutually_exclusive_group(
        required=False)
    font_before_input_group.add_argument("-fb",
                                         "--fonts-before",
                                         nargs="+",
                                         help="Paths to previous fonts")
    font_before_input_group.add_argument(
        "-prb",
        "--pull-request-before",
        help="Get previous fonts from a Github pull request")
    font_before_input_group.add_argument(
        "-ghb",
        "--github-dir-before",
        help="Get previous fonts from a Github dir")
    font_before_input_group.add_argument(
        "-gfb",
        "--googlefonts-before",
        action="store_true",
        help="Get previous fonts from Google Fonts",
    )

    check_group = parser.add_argument_group(title="QA checks")
    check_group.add_argument(
        "-a",
        "--auto-qa",
        action="store_true",
        help=
        "Check fonts against against the same fonts hosted on Google Fonts",
    )
    check_group.add_argument("--diffenator",
                             action="store_true",
                             help="Run Fontdiffenator")
    check_group.add_argument("--diffbrowsers",
                             action="store_true",
                             help="Run Diffbrowsers")
    check_group.add_argument("--fontbakery",
                             action="store_true",
                             help="Run FontBakery")
    check_group.add_argument(
        "--plot-glyphs",
        action="store_true",
        help="Gen images of full charset, useful for new familes",
    )
    check_group.add_argument(
        "--browser-previews",
        action="store_true",
        help="Gen images on diff browsers, useful for new families",
    )
    check_group.add_argument("-dm",
                             "--diff-mode",
                             choices=("weak", "normal", "strict"),
                             default="normal")
    parser.add_argument("-re", "--filter-fonts", help="Filter fonts by regex")
    parser.add_argument("-o",
                        "--out",
                        default="out",
                        help="Output path for check results")
    parser.add_argument(
        "-ogh",
        "--out-github",
        action="store_true",
        help=("Post report data to either the pull request as a comment "
              "open a new issue. This can only be used if fonts have been "
              "fetched from either a pull request or github dir."),
    )
    parser.add_argument(
        "--out-url",
        help=(
            "Post report data to a github pr. This can be used with any font "
            "fetching method."))
    parser.add_argument("--version", action="version", version=__version__)
    args = parser.parse_args()
    if args.out_github and not any([args.pull_request, args.github_dir]):
        raise Exception(
            "Cannot upload results to a github issue or pr. "
            "Font input must either a github dir or a pull request")
    if not any([
            args.auto_qa, args.fontbakery, args.plot_glyphs, args.diffbrowsers,
            args.diffenator, args.browser_previews
    ]):
        raise Exception("Terminating. No checks selected. Run gftools qa "
                        "--help to see all possible commands.")

    # Retrieve fonts and store in out dir
    mkdir(args.out)
    fonts_dir = os.path.join(args.out, "fonts")
    mkdir(fonts_dir)
    if args.fonts:
        [shutil.copy(f, fonts_dir) for f in args.fonts]
        fonts = args.fonts
    elif args.pull_request:
        fonts = download_files_in_github_pr(
            args.pull_request,
            fonts_dir,
            ignore_static_dir=False,
        )
        if not fonts:
            logger.info("No fonts found in pull request. Skipping")
            return
    elif args.github_dir:
        fonts = download_files_in_github_dir(args.github_dir, fonts_dir)
        if not fonts:
            logger.info("No fonts found in github dir. Skipping")
            return
    elif args.googlefonts:
        fonts = download_family_from_Google_Fonts(args.googlefonts, fonts_dir)

    if args.filter_fonts:
        re_filter = re.compile(args.filter_fonts)
        fonts = [f for f in fonts if re_filter.search(f)]

    ttfonts = [
        TTFont(f) for f in fonts
        if f.endswith((".ttf", ".otf")) and "static" not in f
    ]
    family_name = family_name_from_fonts(ttfonts)
    family_on_gf = Google_Fonts_has_family(family_name)

    # Retrieve fonts_before and store in out dir
    fonts_before = None
    if any([args.fonts_before, args.pull_request_before, args.github_dir_before]) or \
           (args.googlefonts_before and family_on_gf):
        fonts_before_dir = os.path.join(args.out, "fonts_before")
        mkdir(fonts_before_dir, overwrite=False)
    if args.fonts_before:
        [shutil.copy(f, fonts_before_dir) for f in args.fonts_before]
        fonts_before = args.fonts_before
    elif args.pull_request_before:
        fonts_before = download_files_in_github_pr(args.pull_request_before,
                                                   fonts_before_dir,
                                                   ignore_static_dir=False)
    elif args.github_dir_before:
        fonts_before = download_files_in_github_dir(args.github_dir_before,
                                                    fonts_before_dir)
    elif args.googlefonts_before and family_on_gf:
        fonts_before = download_family_from_Google_Fonts(
            family_name, fonts_before_dir)

    if fonts_before:
        ttfonts_before = [
            TTFont(f) for f in fonts_before
            if f.endswith((".ttf", ".otf")) and "static" not in f
        ]
        qa = FontQA(ttfonts, ttfonts_before, args.out)
    else:
        qa = FontQA(ttfonts, out=args.out)

    if args.auto_qa and family_on_gf:
        qa.googlefonts_upgrade()
    elif args.auto_qa and not family_on_gf:
        qa.googlefonts_new()
    if args.plot_glyphs:
        qa.plot_glyphs()
    if args.browser_previews:
        qa.browser_previews()
    if args.fontbakery:
        qa.fontbakery()
    if args.diffenator:
        qa.diffenator()
    if args.diffbrowsers:
        qa.diffbrowsers()

    if args.out_url:
        qa.post_to_github(args.out_url)
    elif args.out_github and args.pull_request:
        qa.post_to_github(args.pull_request)
    elif args.out_github and args.github_dir:
        qa.post_to_github(args.github_dir)