<!doctype html><html lang="en">
 <head>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
  <meta content="width=device-width, initial-scale=1, shrink-to-fit=no" name="viewport">
  <title>p1062R0: Diet Graphics</title>
<style data-fill-with="stylesheet">/******************************************************************************
 *                   Style sheet for the W3C specifications                   *
 *
 * Special classes handled by this style sheet include:
 *
 * Indices
 *   - .toc for the Table of Contents (<ol class="toc">)
 *     + <span class="secno"> for the section numbers
 *   - #toc for the Table of Contents (<nav id="toc">)
 *   - ul.index for Indices (<a href="#ref">term</a><span>, in §N.M</span>)
 *   - table.index for Index Tables (e.g. for properties or elements)
 *
 * Structural Markup
 *   - table.data for general data tables
 *     -> use 'scope' attribute, <colgroup>, <thead>, and <tbody> for best results !
 *     -> use <table class='complex data'> for extra-complex tables
 *     -> use <td class='long'> for paragraph-length cell content
 *     -> use <td class='pre'> when manual line breaks/indentation would help readability
 *   - dl.switch for switch statements
 *   - ol.algorithm for algorithms (helps to visualize nesting)
 *   - .figure and .caption (HTML4) and figure and figcaption (HTML5)
 *     -> .sidefigure for right-floated figures
 *   - ins/del
 *
 * Code
 *   - pre and code
 *
 * Special Sections
 *   - .note       for informative notes             (div, p, span, aside, details)
 *   - .example    for informative examples          (div, p, pre, span)
 *   - .issue      for issues                        (div, p, span)
 *   - .assertion  for assertions                    (div, p, span)
 *   - .advisement for loud normative statements     (div, p, strong)
 *   - .annoying-warning for spec obsoletion notices (div, aside, details)
 *
 * Definition Boxes
 *   - pre.def   for WebIDL definitions
 *   - table.def for tables that define other entities (e.g. CSS properties)
 *   - dl.def    for definition lists that define other entitles (e.g. HTML elements)
 *
 * Numbering
 *   - .secno for section numbers in .toc and headings (<span class='secno'>3.2</span>)
 *   - .marker for source-inserted example/figure/issue numbers (<span class='marker'>Issue 4</span>)
 *   - ::before styled for CSS-generated issue/example/figure numbers:
 *     -> Documents wishing to use this only need to add
 *        figcaption::before,
 *        .caption::before { content: "Figure "  counter(figure) " ";  }
 *        .example::before { content: "Example " counter(example) " "; }
 *        .issue::before   { content: "Issue "   counter(issue) " ";   }
 *
 * Header Stuff (ignore, just don't conflict with these classes)
 *   - .head for the header
 *   - .copyright for the copyright
 *
 * Miscellaneous
 *   - .overlarge for things that should be as wide as possible, even if
 *     that overflows the body text area. This can be used on an item or
 *     on its container, depending on the effect desired.
 *     Note that this styling basically doesn't help at all when printing,
 *     since A4 paper isn't much wider than the max-width here.
 *     It's better to design things to fit into a narrower measure if possible.
 *   - js-added ToC jump links (see fixup.js)
 *
 ******************************************************************************/

/******************************************************************************/
/*                                   Body                                     */
/******************************************************************************/

	body {
		counter-reset: example figure issue;

		/* Layout */
		max-width: 50em;               /* limit line length to 50em for readability   */
		margin: 0 auto;                /* center text within page                     */
		padding: 1.6em 1.5em 2em 50px; /* assume 16px font size for downlevel clients */
		padding: 1.6em 1.5em 2em calc(26px + 1.5em); /* leave space for status flag     */

		/* Typography */
		line-height: 1.5;
		font-family: sans-serif;
		widows: 2;
		orphans: 2;
		word-wrap: break-word;
		overflow-wrap: break-word;
		hyphens: auto;

		/* Colors */
		color: black;
		background: white top left fixed no-repeat;
		background-size: 25px auto;
	}


/******************************************************************************/
/*                         Front Matter & Navigation                          */
/******************************************************************************/

/** Header ********************************************************************/

	div.head { margin-bottom: 1em }
	div.head hr { border-style: solid; }

	div.head h1 {
		font-weight: bold;
		margin: 0 0 .1em;
		font-size: 220%;
	}

	div.head h2 { margin-bottom: 1.5em;}

/** W3C Logo ******************************************************************/

	.head .logo {
		float: right;
		margin: 0.4rem 0 0.2rem .4rem;
	}

	.head img[src*="logos/W3C"] {
		display: block;
		border: solid #1a5e9a;
		border-width: .65rem .7rem .6rem;
		border-radius: .4rem;
		background: #1a5e9a;
		color: white;
		font-weight: bold;
	}

	.head a:hover > img[src*="logos/W3C"],
	.head a:focus > img[src*="logos/W3C"] {
		opacity: .8;
	}

	.head a:active > img[src*="logos/W3C"] {
		background: #c00;
		border-color: #c00;
	}

	/* see also additional rules in Link Styling section */

/** Copyright *****************************************************************/

	p.copyright,
	p.copyright small { font-size: small }

/** Back to Top / ToC Toggle **************************************************/

	@media print {
		#toc-nav {
			display: none;
		}
	}
	@media not print {
		#toc-nav {
			position: fixed;
			z-index: 2;
			bottom: 0; left: 0;
			margin: 0;
			min-width: 1.33em;
			border-top-right-radius: 2rem;
			box-shadow: 0 0 2px;
			font-size: 1.5em;
			color: black;
		}
		#toc-nav > a {
			display: block;
			white-space: nowrap;

			height: 1.33em;
			padding: .1em 0.3em;
			margin: 0;

			background: white;
			box-shadow: 0 0 2px;
			border: none;
			border-top-right-radius: 1.33em;
			background: white;
		}
		#toc-nav > #toc-jump {
			padding-bottom: 2em;
			margin-bottom: -1.9em;
		}

		#toc-nav > a:hover,
		#toc-nav > a:focus {
			background: #f8f8f8;
		}
		#toc-nav > a:not(:hover):not(:focus) {
			color: #707070;
		}

		/* statusbar gets in the way on keyboard focus; remove once browsers fix */
		#toc-nav > a[href="#toc"]:not(:hover):focus:last-child {
			padding-bottom: 1.5rem;
		}

		#toc-nav:not(:hover) > a:not(:focus) > span + span {
			/* Ideally this uses :focus-within on #toc-nav */
			display: none;
		}
		#toc-nav > a > span + span {
			padding-right: 0.2em;
		}

		#toc-toggle-inline {
			vertical-align: 0.05em;
			font-size: 80%;
			color: gray;
			color: hsla(203,20%,40%,.7);
			border-style: none;
			background: transparent;
			position: relative;
		}
		#toc-toggle-inline:hover:not(:active),
		#toc-toggle-inline:focus:not(:active) {
			text-shadow: 1px 1px silver;
			top: -1px;
			left: -1px;
		}

		#toc-nav :active {
			color: #C00;
		}
	}

/** ToC Sidebar ***************************************************************/

	/* Floating sidebar */
	@media screen {
		body.toc-sidebar #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			max-width: 80%;
			max-width: calc(100% - 2em - 26px);
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body.toc-sidebar #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}
		body.toc-sidebar #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	/* Hide main scroller when only the ToC is visible anyway */
	@media screen and (max-width: 28em) {
		body.toc-sidebar {
			overflow: hidden;
		}
	}

	/* Sidebar with its own space */
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) #toc {
			position: fixed;
			top: 0; bottom: 0;
			left: 0;
			width: 23.5em;
			overflow: auto;
			padding: 0 1em;
			padding-left: 42px;
			padding-left: calc(1em + 26px);
			background: inherit;
			background-color: #f7f8f9;
			z-index: 1;
			box-shadow: -.1em 0 .25em rgba(0,0,0,.1) inset;
		}
		body:not(.toc-inline) #toc h2 {
			margin-top: .8rem;
			font-variant: small-caps;
			font-variant: all-small-caps;
			text-transform: lowercase;
			font-weight: bold;
			color: gray;
			color: hsla(203,20%,40%,.7);
		}

		body:not(.toc-inline) {
			padding-left: 29em;
		}
		/* See also Overflow section at the bottom */

		body:not(.toc-inline) #toc-jump:not(:focus) {
			width: 0;
			height: 0;
			padding: 0;
			position: absolute;
			overflow: hidden;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) {
			margin: 0 4em;
		}
	}

/******************************************************************************/
/*                                Sectioning                                  */
/******************************************************************************/

/** Headings ******************************************************************/

	h1, h2, h3, h4, h5, h6, dt {
		page-break-after: avoid;
		page-break-inside: avoid;
		font: 100% sans-serif;   /* Reset all font styling to clear out UA styles */
		font-family: inherit;    /* Inherit the font family. */
		line-height: 1.2;        /* Keep wrapped headings compact */
		hyphens: manual;         /* Hyphenated headings look weird */
	}

	h2, h3, h4, h5, h6 {
		margin-top: 3rem;
	}

	h1, h2, h3 {
		color: #005A9C;
		background: transparent;
	}

	h1 { font-size: 170%; }
	h2 { font-size: 140%; }
	h3 { font-size: 120%; }
	h4 { font-weight: bold; }
	h5 { font-style: italic; }
	h6 { font-variant: small-caps; }
	dt { font-weight: bold; }

/** Subheadings ***************************************************************/

	h1 + h2,
	#subtitle {
		/* #subtitle is a subtitle in an H2 under the H1 */
		margin-top: 0;
	}
	h2 + h3,
	h3 + h4,
	h4 + h5,
	h5 + h6 {
		margin-top: 1.2em; /* = 1 x line-height */
	}

/** Section divider ***********************************************************/

	:not(.head) > hr {
		font-size: 1.5em;
		text-align: center;
		margin: 1em auto;
		height: auto;
		border: transparent solid 0;
		background: transparent;
	}
	:not(.head) > hr::before {
		content: "\2727\2003\2003\2727\2003\2003\2727";
	}

/******************************************************************************/
/*                            Paragraphs and Lists                            */
/******************************************************************************/

	p {
		margin: 1em 0;
	}

	dd > p:first-child,
	li > p:first-child {
		margin-top: 0;
	}

	ul, ol {
		margin-left: 0;
		padding-left: 2em;
	}

	li {
		margin: 0.25em 0 0.5em;
		padding: 0;
	}

	dl dd {
		margin: 0 0 .5em 2em;
	}

	.head dd + dd { /* compact for header */
		margin-top: -.5em;
	}

	/* Style for algorithms */
	ol.algorithm ol:not(.algorithm),
	.algorithm > ol ol:not(.algorithm) {
	 border-left: 0.5em solid #DEF;
	}

	/* Put nice boxes around each algorithm. */
	[data-algorithm]:not(.heading) {
	  padding: .5em;
	  border: thin solid #ddd; border-radius: .5em;
	  margin: .5em calc(-0.5em - 1px);
	}
	[data-algorithm]:not(.heading) > :first-child {
	  margin-top: 0;
	}
	[data-algorithm]:not(.heading) > :last-child {
	  margin-bottom: 0;
	}

	/* Style for switch/case <dl>s */
	dl.switch > dd > ol.only,
	dl.switch > dd > .only > ol {
	 margin-left: 0;
	}
	dl.switch > dd > ol.algorithm,
	dl.switch > dd > .algorithm > ol {
	 margin-left: -2em;
	}
	dl.switch {
	 padding-left: 2em;
	}
	dl.switch > dt {
	 text-indent: -1.5em;
	 margin-top: 1em;
	}
	dl.switch > dt + dt {
	 margin-top: 0;
	}
	dl.switch > dt::before {
	 content: '\21AA';
	 padding: 0 0.5em 0 0;
	 display: inline-block;
	 width: 1em;
	 text-align: right;
	 line-height: 0.5em;
	}

/** Terminology Markup ********************************************************/


/******************************************************************************/
/*                                 Inline Markup                              */
/******************************************************************************/

/** Terminology Markup ********************************************************/
	dfn   { /* Defining instance */
		font-weight: bolder;
	}
	a > i { /* Instance of term */
		font-style: normal;
	}
	dt dfn code, code.idl {
		font-size: medium;
	}
	dfn var {
		font-style: normal;
	}

/** Change Marking ************************************************************/

	del { color: red;  text-decoration: line-through; }
	ins { color: #080; text-decoration: underline;    }

/** Miscellaneous improvements to inline formatting ***************************/

	sup {
		vertical-align: super;
		font-size: 80%
	}

/******************************************************************************/
/*                                    Code                                    */
/******************************************************************************/

/** General monospace/pre rules ***********************************************/

	pre, code, samp {
		font-family: Menlo, Consolas, "DejaVu Sans Mono", Monaco, monospace;
		font-size: .9em;
		page-break-inside: avoid;
		hyphens: none;
		text-transform: none;
	}
	pre code,
	code code {
		font-size: 100%;
	}

	pre {
		margin-top: 1em;
		margin-bottom: 1em;
		overflow: auto;
	}

/** Inline Code fragments *****************************************************/

  /* Do something nice. */

/******************************************************************************/
/*                                    Links                                   */
/******************************************************************************/

/** General Hyperlinks ********************************************************/

	/* We hyperlink a lot, so make it less intrusive */
	a[href] {
		color: #034575;
		text-decoration: none;
		border-bottom: 1px solid #707070;
		/* Need a bit of extending for it to look okay */
		padding: 0 1px 0;
		margin: 0 -1px 0;
	}
	a:visited {
		border-bottom-color: #BBB;
	}

	/* Use distinguishing colors when user is interacting with the link */
	a[href]:focus,
	a[href]:hover {
		background: #f8f8f8;
		background: rgba(75%, 75%, 75%, .25);
		border-bottom-width: 3px;
		margin-bottom: -2px;
	}
	a[href]:active {
		color: #C00;
		border-color: #C00;
	}

	/* Backout above styling for W3C logo */
	.head .logo,
	.head .logo a {
		border: none;
		text-decoration: none;
		background: transparent;
	}

/******************************************************************************/
/*                                    Images                                  */
/******************************************************************************/

	img {
		border-style: none;
	}

	/* For autogen numbers, add
	   .caption::before, figcaption::before { content: "Figure " counter(figure) ". "; }
	*/

	figure, .figure, .sidefigure {
		page-break-inside: avoid;
		text-align: center;
		margin: 2.5em 0;
	}
	.figure img,    .sidefigure img,    figure img,
	.figure object, .sidefigure object, figure object {
		max-width: 100%;
		margin: auto;
	}
	.figure pre, .sidefigure pre, figure pre {
		text-align: left;
		display: table;
		margin: 1em auto;
	}
	.figure table, figure table {
		margin: auto;
	}
	@media screen and (min-width: 20em) {
		.sidefigure {
			float: right;
			width: 50%;
			margin: 0 0 0.5em 0.5em
		}
	}
	.caption, figcaption, caption {
		font-style: italic;
		font-size: 90%;
	}
	.caption::before, figcaption::before, figcaption > .marker {
		font-weight: bold;
	}
	.caption, figcaption {
		counter-increment: figure;
	}

	/* DL list is indented 2em, but figure inside it is not */
	dd > .figure, dd > figure { margin-left: -2em }

/******************************************************************************/
/*                             Colored Boxes                                  */
/******************************************************************************/

	.issue, .note, .example, .assertion, .advisement, blockquote {
		padding: .5em;
		border: .5em;
		border-left-style: solid;
		page-break-inside: avoid;
	}
	span.issue, span.note {
		padding: .1em .5em .15em;
		border-right-style: solid;
	}

	.issue,
	.note,
	.example,
	.advisement,
	.assertion,
	blockquote {
		margin: 1em auto;
	}
	.note  > p:first-child,
	.issue > p:first-child,
	blockquote > :first-child {
		margin-top: 0;
	}
	blockquote > :last-child {
		margin-bottom: 0;
	}

/** Blockquotes ***************************************************************/

	blockquote {
		border-color: silver;
	}

/** Open issue ****************************************************************/

	.issue {
		border-color: #E05252;
		background: #FBE9E9;
		counter-increment: issue;
		overflow: auto;
	}
	.issue::before, .issue > .marker {
		text-transform: uppercase;
		color: #AE1E1E;
		padding-right: 1em;
		text-transform: uppercase;
	}
	/* Add .issue::before { content: "Issue " counter(issue) " "; } for autogen numbers,
	   or use class="marker" to mark up the issue number in source. */

/** Example *******************************************************************/

	.example {
		border-color: #E0CB52;
		background: #FCFAEE;
		counter-increment: example;
		overflow: auto;
		clear: both;
	}
	.example::before, .example > .marker {
		text-transform: uppercase;
		color: #827017;
		min-width: 7.5em;
		display: block;
	}
	/* Add .example::before { content: "Example " counter(example) " "; } for autogen numbers,
	   or use class="marker" to mark up the example number in source. */

/** Non-normative Note ********************************************************/

	.note {
		border-color: #52E052;
		background: #E9FBE9;
		overflow: auto;
	}

	.note::before, .note > .marker,
	details.note > summary::before,
	details.note > summary > .marker {
		text-transform: uppercase;
		display: block;
		color: hsl(120, 70%, 30%);
	}
	/* Add .note::before { content: "Note"; } for autogen label,
	   or use class="marker" to mark up the label in source. */

	details.note > summary {
		display: block;
		color: hsl(120, 70%, 30%);
	}
	details.note[open] > summary {
		border-bottom: 1px silver solid;
	}

/** Assertion Box *************************************************************/
	/*  for assertions in algorithms */

	.assertion {
		border-color: #AAA;
		background: #EEE;
	}

/** Advisement Box ************************************************************/
	/*  for attention-grabbing normative statements */

	.advisement {
		border-color: orange;
		border-style: none solid;
		background: #FFEECC;
	}
	strong.advisement {
		display: block;
		text-align: center;
	}
	.advisement > .marker {
		color: #B35F00;
	}

/** Spec Obsoletion Notice ****************************************************/
	/* obnoxious obsoletion notice for older/abandoned specs. */

	details {
		display: block;
	}
	summary {
		font-weight: bolder;
	}

	.annoying-warning:not(details),
	details.annoying-warning:not([open]) > summary,
	details.annoying-warning[open] {
		background: #fdd;
		color: red;
		font-weight: bold;
		padding: .75em 1em;
		border: thick red;
		border-style: solid;
		border-radius: 1em;
	}
	.annoying-warning :last-child {
		margin-bottom: 0;
	}

@media not print {
	details.annoying-warning[open] {
		position: fixed;
		left: 1em;
		right: 1em;
		bottom: 1em;
		z-index: 1000;
	}
}

	details.annoying-warning:not([open]) > summary {
		text-align: center;
	}

/** Entity Definition Boxes ***************************************************/

	.def {
		padding: .5em 1em;
		background: #DEF;
		margin: 1.2em 0;
		border-left: 0.5em solid #8CCBF2;
	}

/******************************************************************************/
/*                                    Tables                                  */
/******************************************************************************/

	th, td {
		text-align: left;
		text-align: start;
	}

/** Property/Descriptor Definition Tables *************************************/

	table.def {
		/* inherits .def box styling, see above */
		width: 100%;
		border-spacing: 0;
	}

	table.def td,
	table.def th {
		padding: 0.5em;
		vertical-align: baseline;
		border-bottom: 1px solid #bbd7e9;
	}

	table.def > tbody > tr:last-child th,
	table.def > tbody > tr:last-child td {
		border-bottom: 0;
	}

	table.def th {
		font-style: italic;
		font-weight: normal;
		padding-left: 1em;
		width: 3em;
	}

	/* For when values are extra-complex and need formatting for readability */
	table td.pre {
		white-space: pre-wrap;
	}

	/* A footnote at the bottom of a def table */
	table.def           td.footnote {
		padding-top: 0.6em;
	}
	table.def           td.footnote::before {
		content: " ";
		display: block;
		height: 0.6em;
		width: 4em;
		border-top: thin solid;
	}

/** Data tables (and properly marked-up index tables) *************************/
	/*
		 <table class="data"> highlights structural relationships in a table
		 when correct markup is used (e.g. thead/tbody, th vs. td, scope attribute)

		 Use class="complex data" for particularly complicated tables --
		 (This will draw more lines: busier, but clearer.)

		 Use class="long" on table cells with paragraph-like contents
		 (This will adjust text alignment accordingly.)
		 Alternately use class="longlastcol" on tables, to have the last column assume "long".
	*/

	table {
		word-wrap: normal;
		overflow-wrap: normal;
		hyphens: manual;
	}

	table.data,
	table.index {
		margin: 1em auto;
		border-collapse: collapse;
		border: hidden;
		width: 100%;
	}
	table.data caption,
	table.index caption {
		max-width: 50em;
		margin: 0 auto 1em;
	}

	table.data td,  table.data th,
	table.index td, table.index th {
		padding: 0.5em 1em;
		border-width: 1px;
		border-color: silver;
		border-top-style: solid;
	}

	table.data thead td:empty {
		padding: 0;
		border: 0;
	}

	table.data  thead,
	table.index thead,
	table.data  tbody,
	table.index tbody {
		border-bottom: 2px solid;
	}

	table.data colgroup,
	table.index colgroup {
		border-left: 2px solid;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		border-right: 2px solid;
		border-top: 1px solid silver;
		padding-right: 1em;
	}

	table.data th[colspan],
	table.data td[colspan] {
		text-align: center;
	}

	table.complex.data th,
	table.complex.data td {
		border: 1px solid silver;
		text-align: center;
	}

	table.data.longlastcol td:last-child,
	table.data td.long {
	 vertical-align: baseline;
	 text-align: left;
	}

	table.data img {
		vertical-align: middle;
	}


/*
Alternate table alignment rules

	table.data,
	table.index {
		text-align: center;
	}

	table.data  thead th[scope="row"],
	table.index thead th[scope="row"] {
		text-align: right;
	}

	table.data  tbody th:first-child,
	table.index tbody th:first-child  {
		text-align: right;
	}

Possible extra rowspan handling

	table.data  tbody th[rowspan]:not([rowspan='1']),
	table.index tbody th[rowspan]:not([rowspan='1']),
	table.data  tbody td[rowspan]:not([rowspan='1']),
	table.index tbody td[rowspan]:not([rowspan='1']) {
		border-left: 1px solid silver;
	}

	table.data  tbody th[rowspan]:first-child,
	table.index tbody th[rowspan]:first-child,
	table.data  tbody td[rowspan]:first-child,
	table.index tbody td[rowspan]:first-child{
		border-left: 0;
		border-right: 1px solid silver;
	}
*/

/******************************************************************************/
/*                                  Indices                                   */
/******************************************************************************/


/** Table of Contents *********************************************************/

	.toc a {
		/* More spacing; use padding to make it part of the click target. */
		padding-top: 0.1rem;
		/* Larger, more consistently-sized click target */
		display: block;
		/* Reverse color scheme */
		color: black;
		border-color: #3980B5;
		border-bottom-width: 3px !important;
		margin-bottom: 0px !important;
	}
	.toc a:visited {
		border-color: #054572;
	}
	.toc a:not(:focus):not(:hover) {
		/* Allow colors to cascade through from link styling */
		border-bottom-color: transparent;
	}

	.toc, .toc ol, .toc ul, .toc li {
		list-style: none; /* Numbers must be inlined into source */
		/* because generated content isn't search/selectable and markers can't do multilevel yet */
		margin:  0;
		padding: 0;
		line-height: 1.1rem; /* consistent spacing */
	}

	/* ToC not indented until third level, but font style & margins show hierarchy */
	.toc > li             { font-weight: bold;   }
	.toc > li li          { font-weight: normal; }
	.toc > li li li       { font-size:   95%;    }
	.toc > li li li li    { font-size:   90%;    }
	.toc > li li li li li { font-size:   85%;    }

	.toc > li             { margin: 1.5rem 0;    }
	.toc > li li          { margin: 0.3rem 0;    }
	.toc > li li li       { margin-left: 2rem;   }

	/* Section numbers in a column of their own */
	.toc .secno {
		float: left;
		width: 4rem;
		white-space: nowrap;
	}
	.toc > li li li li .secno {
		font-size: 85%;
	}
	.toc > li li li li li .secno {
		font-size: 100%;
	}

	:not(li) > .toc              { margin-left:  5rem; }
	.toc .secno                  { margin-left: -5rem; }
	.toc > li li li .secno       { margin-left: -7rem; }
	.toc > li li li li .secno    { margin-left: -9rem; }
	.toc > li li li li li .secno { margin-left: -11rem; }

	/* Tighten up indentation in narrow ToCs */
	@media (max-width: 30em) {
		:not(li) > .toc              { margin-left:  4rem; }
		.toc .secno                  { margin-left: -4rem; }
		.toc > li li li              { margin-left:  1rem; }
		.toc > li li li .secno       { margin-left: -5rem; }
		.toc > li li li li .secno    { margin-left: -6rem; }
		.toc > li li li li li .secno { margin-left: -7rem; }
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) :not(li) > .toc              { margin-left:  4rem; }
		body:not(.toc-inline) .toc .secno                  { margin-left: -4rem; }
		body:not(.toc-inline) .toc > li li li              { margin-left:  1rem; }
		body:not(.toc-inline) .toc > li li li .secno       { margin-left: -5rem; }
		body:not(.toc-inline) .toc > li li li li .secno    { margin-left: -6rem; }
		body:not(.toc-inline) .toc > li li li li li .secno { margin-left: -7rem; }
	}
	body.toc-sidebar #toc :not(li) > .toc              { margin-left:  4rem; }
	body.toc-sidebar #toc .toc .secno                  { margin-left: -4rem; }
	body.toc-sidebar #toc .toc > li li li              { margin-left:  1rem; }
	body.toc-sidebar #toc .toc > li li li .secno       { margin-left: -5rem; }
	body.toc-sidebar #toc .toc > li li li li .secno    { margin-left: -6rem; }
	body.toc-sidebar #toc .toc > li li li li li .secno { margin-left: -7rem; }

	.toc li {
		clear: both;
	}


/** Index *********************************************************************/

	/* Index Lists: Layout */
	ul.index       { margin-left: 0; columns: 15em; text-indent: 1em hanging; }
	ul.index li    { margin-left: 0; list-style: none; break-inside: avoid; }
	ul.index li li { margin-left: 1em }
	ul.index dl    { margin-top: 0; }
	ul.index dt    { margin: .2em 0 .2em 20px;}
	ul.index dd    { margin: .2em 0 .2em 40px;}
	/* Index Lists: Typography */
	ul.index ul,
	ul.index dl { font-size: smaller; }
	@media not print {
		ul.index li span {
			white-space: nowrap;
			color: transparent; }
		ul.index li a:hover + span,
		ul.index li a:focus + span {
			color: #707070;
		}
	}

/** Index Tables *****************************************************/
	/* See also the data table styling section, which this effectively subclasses */

	table.index {
		font-size: small;
		border-collapse: collapse;
		border-spacing: 0;
		text-align: left;
		margin: 1em 0;
	}

	table.index td,
	table.index th {
		padding: 0.4em;
	}

	table.index tr:hover td:not([rowspan]),
	table.index tr:hover th:not([rowspan]) {
		background: #f7f8f9;
	}

	/* The link in the first column in the property table (formerly a TD) */
	table.index th:first-child a {
		font-weight: bold;
	}

/******************************************************************************/
/*                                    Print                                   */
/******************************************************************************/

	@media print {
		/* Pages have their own margins. */
		html {
			margin: 0;
		}
		/* Serif for print. */
		body {
			font-family: serif;
		}
	}
	@page {
		margin: 1.5cm 1.1cm;
	}

/******************************************************************************/
/*                                    Legacy                                  */
/******************************************************************************/

	/* This rule is inherited from past style sheets. No idea what it's for. */
	.hide { display: none }



/******************************************************************************/
/*                             Overflow Control                               */
/******************************************************************************/

	.figure .caption, .sidefigure .caption, figcaption {
		/* in case figure is overlarge, limit caption to 50em */
		max-width: 50rem;
		margin-left: auto;
		margin-right: auto;
	}
	.overlarge > table {
		/* limit preferred width of table */
		max-width: 50em;
		margin-left: auto;
		margin-right: auto;
	}

	@media (min-width: 55em) {
		.overlarge {
			margin-left: calc(13px + 26.5rem - 50vw);
			margin-right: calc(13px + 26.5rem - 50vw);
			max-width: none;
		}
	}
	@media screen and (min-width: 78em) {
		body:not(.toc-inline) .overlarge {
			/* 30.5em body padding 50em content area */
			margin-left: calc(40em - 50vw) !important;
			margin-right: calc(40em - 50vw) !important;
		}
	}
	@media screen and (min-width: 90em) {
		body:not(.toc-inline) .overlarge {
			/* 4em html margin 30.5em body padding 50em content area */
			margin-left: 0 !important;
			margin-right: calc(84.5em - 100vw) !important;
		}
	}

	@media not print {
		.overlarge {
			overflow-x: auto;
			/* See Lea Verou's explanation background-attachment:
			 * http://lea.verou.me/2012/04/background-attachment-local/
			 *
			background: top left  / 4em 100% linear-gradient(to right,  #ffffff, rgba(255, 255, 255, 0)) local,
			            top right / 4em 100% linear-gradient(to left, #ffffff, rgba(255, 255, 255, 0)) local,
			            top left  / 1em 100% linear-gradient(to right,  #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            top right / 1em 100% linear-gradient(to left, #c3c3c5, rgba(195, 195, 197, 0)) scroll,
			            white;
			background-repeat: no-repeat;
			*/
		}
	}
</style>
<style type="text/css">
    table, th, td {
      border: 1px solid black;
      border-collapse: collapse;
      vertical-align: top;
    }
    th, td {
      border-left: none;
      border-right: none;
      padding: 0px 10px;
    }
    th {
      text-align: center;
    }
  </style>
  <meta content="Bikeshed version 4ed3ee986a8d1722dd7c6bb819b1a2484c3cfb47" name="generator">
  <link href="http://wg21.link/P1062r0" rel="canonical">
  <meta content="aad7f971609e373fbdd1c6d3fad779796fd21bfc" name="document-revision">
<style>/* style-md-lists */

/* This is a weird hack for me not yet following the commonmark spec
   regarding paragraph and lists. */
[data-md] > :first-child {
    margin-top: 0;
}
[data-md] > :last-child {
    margin-bottom: 0;
}</style>
<style>/* style-counters */

body {
    counter-reset: example figure issue;
}
.issue {
    counter-increment: issue;
}
.issue:not(.no-marker)::before {
    content: "Issue " counter(issue);
}

.example {
    counter-increment: example;
}
.example:not(.no-marker)::before {
    content: "Example " counter(example);
}
.invalid.example:not(.no-marker)::before,
.illegal.example:not(.no-marker)::before {
    content: "Invalid Example" counter(example);
}

figcaption {
    counter-increment: figure;
}
figcaption:not(.no-marker)::before {
    content: "Figure " counter(figure) " ";
}</style>
<style>/* style-syntax-highlighting */

.highlight:not(.idl) { background: hsl(24, 20%, 95%); }
code.highlight { padding: .1em; border-radius: .3em; }
pre.highlight, pre > code.highlight { display: block; padding: 1em; margin: .5em 0; overflow: auto; border-radius: 0; }
.highlight .c { color: #708090 } /* Comment */
.highlight .k { color: #990055 } /* Keyword */
.highlight .l { color: #000000 } /* Literal */
.highlight .n { color: #0077aa } /* Name */
.highlight .o { color: #999999 } /* Operator */
.highlight .p { color: #999999 } /* Punctuation */
.highlight .cm { color: #708090 } /* Comment.Multiline */
.highlight .cp { color: #708090 } /* Comment.Preproc */
.highlight .c1 { color: #708090 } /* Comment.Single */
.highlight .cs { color: #708090 } /* Comment.Special */
.highlight .kc { color: #990055 } /* Keyword.Constant */
.highlight .kd { color: #990055 } /* Keyword.Declaration */
.highlight .kn { color: #990055 } /* Keyword.Namespace */
.highlight .kp { color: #990055 } /* Keyword.Pseudo */
.highlight .kr { color: #990055 } /* Keyword.Reserved */
.highlight .kt { color: #990055 } /* Keyword.Type */
.highlight .ld { color: #000000 } /* Literal.Date */
.highlight .m { color: #000000 } /* Literal.Number */
.highlight .s { color: #a67f59 } /* Literal.String */
.highlight .na { color: #0077aa } /* Name.Attribute */
.highlight .nc { color: #0077aa } /* Name.Class */
.highlight .no { color: #0077aa } /* Name.Constant */
.highlight .nd { color: #0077aa } /* Name.Decorator */
.highlight .ni { color: #0077aa } /* Name.Entity */
.highlight .ne { color: #0077aa } /* Name.Exception */
.highlight .nf { color: #0077aa } /* Name.Function */
.highlight .nl { color: #0077aa } /* Name.Label */
.highlight .nn { color: #0077aa } /* Name.Namespace */
.highlight .py { color: #0077aa } /* Name.Property */
.highlight .nt { color: #669900 } /* Name.Tag */
.highlight .nv { color: #222222 } /* Name.Variable */
.highlight .ow { color: #999999 } /* Operator.Word */
.highlight .mb { color: #000000 } /* Literal.Number.Bin */
.highlight .mf { color: #000000 } /* Literal.Number.Float */
.highlight .mh { color: #000000 } /* Literal.Number.Hex */
.highlight .mi { color: #000000 } /* Literal.Number.Integer */
.highlight .mo { color: #000000 } /* Literal.Number.Oct */
.highlight .sb { color: #a67f59 } /* Literal.String.Backtick */
.highlight .sc { color: #a67f59 } /* Literal.String.Char */
.highlight .sd { color: #a67f59 } /* Literal.String.Doc */
.highlight .s2 { color: #a67f59 } /* Literal.String.Double */
.highlight .se { color: #a67f59 } /* Literal.String.Escape */
.highlight .sh { color: #a67f59 } /* Literal.String.Heredoc */
.highlight .si { color: #a67f59 } /* Literal.String.Interpol */
.highlight .sx { color: #a67f59 } /* Literal.String.Other */
.highlight .sr { color: #a67f59 } /* Literal.String.Regex */
.highlight .s1 { color: #a67f59 } /* Literal.String.Single */
.highlight .ss { color: #a67f59 } /* Literal.String.Symbol */
.highlight .vc { color: #0077aa } /* Name.Variable.Class */
.highlight .vg { color: #0077aa } /* Name.Variable.Global */
.highlight .vi { color: #0077aa } /* Name.Variable.Instance */
.highlight .il { color: #000000 } /* Literal.Number.Integer.Long */
</style>
<style>/* style-selflinks */

.heading, .issue, .note, .example, li, dt {
    position: relative;
}
a.self-link {
    position: absolute;
    top: 0;
    left: calc(-1 * (3.5rem - 26px));
    width: calc(3.5rem - 26px);
    height: 2em;
    text-align: center;
    border: none;
    transition: opacity .2s;
    opacity: .5;
}
a.self-link:hover {
    opacity: 1;
}
.heading > a.self-link {
    font-size: 83%;
}
li > a.self-link {
    left: calc(-1 * (3.5rem - 26px) - 2em);
}
dfn > a.self-link {
    top: auto;
    left: auto;
    opacity: 0;
    width: 1.5em;
    height: 1.5em;
    background: gray;
    color: white;
    font-style: normal;
    transition: opacity .2s, background-color .2s, color .2s;
}
dfn:hover > a.self-link {
    opacity: 1;
}
dfn > a.self-link:hover {
    color: black;
}

a.self-link::before            { content: "¶"; }
.heading > a.self-link::before { content: "§"; }
dfn > a.self-link::before      { content: "#"; }</style>
<style>/* style-autolinks */

.css.css, .property.property, .descriptor.descriptor {
    color: #005a9c;
    font-size: inherit;
    font-family: inherit;
}
.css::before, .property::before, .descriptor::before {
    content: "‘";
}
.css::after, .property::after, .descriptor::after {
    content: "’";
}
.property, .descriptor {
    /* Don't wrap property and descriptor names */
    white-space: nowrap;
}
.type { /* CSS value <type> */
    font-style: italic;
}
pre .property::before, pre .property::after {
    content: "";
}
[data-link-type="property"]::before,
[data-link-type="propdesc"]::before,
[data-link-type="descriptor"]::before,
[data-link-type="value"]::before,
[data-link-type="function"]::before,
[data-link-type="at-rule"]::before,
[data-link-type="selector"]::before,
[data-link-type="maybe"]::before {
    content: "‘";
}
[data-link-type="property"]::after,
[data-link-type="propdesc"]::after,
[data-link-type="descriptor"]::after,
[data-link-type="value"]::after,
[data-link-type="function"]::after,
[data-link-type="at-rule"]::after,
[data-link-type="selector"]::after,
[data-link-type="maybe"]::after {
    content: "’";
}

[data-link-type].production::before,
[data-link-type].production::after,
.prod [data-link-type]::before,
.prod [data-link-type]::after {
    content: "";
}

[data-link-type=element],
[data-link-type=element-attr] {
    font-family: Menlo, Consolas, "DejaVu Sans Mono", monospace;
    font-size: .9em;
}
[data-link-type=element]::before { content: "<" }
[data-link-type=element]::after  { content: ">" }

[data-link-type=biblio] {
    white-space: pre;
}</style>
 <body class="h-entry">
  <div class="head">
   <p data-fill-with="logo"></p>
   <h1 class="p-name no-ref" id="title">p1062R0<br>Diet Graphics</h1>
   <h2 class="no-num no-toc no-ref heading settled" id="subtitle"><span class="content">Draft Proposal, <time class="dt-updated" datetime="2018-05-07">7 May 2018</time></span></h2>
   <div data-fill-with="spec-metadata">
    <dl>
     <dt>This version:
     <dd><a class="u-url" href="http://wg21.link/P1062r0">http://wg21.link/P1062r0</a>
     <dt>Issue Tracking:
     <dd><a href="https://github.com/brycelelbach/diet_graphics/issues">GitHub</a>
     <dt>Authors:
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:brycelelbach@gmail.com">Bryce Adelstein Lelbach</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:ogiroux@gmail.com">Olivier Giroux</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:whatwasthataddress@gmail.com">Zach Laine</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:corentinjabot@gmail.com">Corentin Jabot</a>
     <dd>
      <dd class="editor p-author h-card vcard"><a class="p-name fn u-email email" href="mailto:vittorio.romeo@outlook.com">Vittorio Romeo</a>
     <dt>Audience:
     <dd>WG21
     <dt>Project:
     <dd>ISO JTC1/SC22/WG21: Programming Language C++
    </dl>
   </div>
   <div data-fill-with="warning"></div>
   <hr title="Separator for header">
  </div>
  <div class="p-summary" data-fill-with="abstract">
   <h2 class="no-num no-toc no-ref heading settled" id="abstract"><span class="content">Abstract</span></h2>
   <p>The proposed programmatic 2D drawing library is not a good fit for C++.</p>
  </div>
  <nav data-fill-with="table-of-contents" id="toc">
   <h2 class="no-num no-toc no-ref" id="contents">Table of Contents</h2>
   <ol class="toc" role="directory">
    <li><a href="#acknowledgments"><span class="secno">1</span> <span class="content">Acknowledgments</span></a>
    <li><a href="#foreword"><span class="secno">2</span> <span class="content">Foreword</span></a>
    <li>
     <a href="#utility"><span class="secno">3</span> <span class="content">Utility</span></a>
     <ol class="toc">
      <li><a href="#teaching"><span class="secno">3.1</span> <span class="content">Teaching</span></a>
      <li>
       <a href="#enabling-graphics-programming"><span class="secno">3.2</span> <span class="content">Enabling Graphics Programming</span></a>
       <ol class="toc">
        <li><a href="#graphical-application-developers"><span class="secno">3.2.1</span> <span class="content">Graphical Application Developers</span></a>
        <li><a href="#graphical-framework-developers"><span class="secno">3.2.2</span> <span class="content">Graphical Framework Developers</span></a>
       </ol>
     </ol>
    <li>
     <a href="#design-issues"><span class="secno">4</span> <span class="content">Design Issues</span></a>
     <ol class="toc">
      <li><a href="#lack-of-batching-operations"><span class="secno">4.1</span> <span class="content">Lack of Batching Operations</span></a>
      <li><a href="#text-and-unicode"><span class="secno">4.2</span> <span class="content">Text and Unicode</span></a>
      <li><a href="#geometry-and-linear-algebra-types"><span class="secno">4.3</span> <span class="content">Geometry and Linear Algebra Types</span></a>
      <li><a href="#new-container-type"><span class="secno">4.4</span> <span class="content">New Container Type</span></a>
     </ol>
    <li>
     <a href="#priorities"><span class="secno">5</span> <span class="content">Priorities</span></a>
     <ol class="toc">
      <li><a href="#committee-resources-are-limited"><span class="secno">5.1</span> <span class="content">Committee Resources are Limited</span></a>
      <li><a href="#what-belongs-in-the-standard"><span class="secno">5.2</span> <span class="content">What Belongs in The Standard?</span></a>
     </ol>
    <li><a href="#suggestions"><span class="secno">6</span> <span class="content">Suggestions</span></a>
    <li><a href="#alternative-minimal-graphics"><span class="secno">7</span> <span class="content">Alternative Minimal Graphics</span></a>
    <li>
     <a href="#references"><span class="secno"></span> <span class="content">References</span></a>
     <ol class="toc">
      <li><a href="#informative"><span class="secno"></span> <span class="content">Informative References</span></a>
     </ol>
   </ol>
  </nav>
  <main>
   <h2 class="heading settled" data-level="1" id="acknowledgments"><span class="secno">1. </span><span class="content">Acknowledgments</span><a class="self-link" href="#acknowledgments"></a></h2>
   <p>We’d like to acknowledge:</p>
   <ul>
    <li data-md="">
     <p>Michael Spencer and Billy Baker, who provided invaluable feedback at a bar.</p>
    <li data-md="">
     <p>Everyone involved in the discussion of <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a> at the Jacksonville 2018 meeting.</p>
   </ul>
   <h2 class="heading settled" data-level="2" id="foreword"><span class="secno">2. </span><span class="content">Foreword</span><a class="self-link" href="#foreword"></a></h2>
   <p>The authors of <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a>, SG13, and everyone else who has worked on the proposed 2D drawing Technical Specification, have put a great amount of work, time and energy in that proposal.
We, the authors of this paper, greatly appreciate their contributions to C++.
We also greatly value them, personally, as they are simply excellent people.</p>
   <p>This paper was difficult to write, because we have no intention to malign their hard work.</p>
   <p>We do not have a negative opinion of the particular library in question.
We do, however, question whether it should be included in the C++ International Standard.</p>
   <p>However, we feel obligated to share our technical perspective on <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a>.
In this paper, we explain why we believe that <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a>, "A Proposal to Add 2D Graphics Rendering and Display to C++" is not a good fit for C++.</p>
   <p><a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a> proposes a programmatic 2D drawing library: it provides programmatic C++ interfaces for drawing <strong>art assets</strong> by manipulating C++ objects and then displaying them on a surface.</p>
   <h2 class="heading settled" data-level="3" id="utility"><span class="secno">3. </span><span class="content">Utility</span><a class="self-link" href="#utility"></a></h2>
   <p>Let’s take a step back and discuss <strong>why</strong> some on the committee have a desire to standardize a 2D drawing library.</p>
   <p>A few different use cases have been espoused during the lifetime of this proposal:</p>
   <ul>
    <li data-md="">
     <p>Improving the teachability of C++.</p>
    <li data-md="">
     <p>Providing programmers with an easy and portable interface suitable for simple 2D graphics tasks.</p>
   </ul>
   <h3 class="heading settled" data-level="3.1" id="teaching"><span class="secno">3.1. </span><span class="content">Teaching</span><a class="self-link" href="#teaching"></a></h3>
   <p>Some of the motivation behind <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a> is a desire to provide a powerful teaching tool for C++.
For new programmers, especially younger programmers, writing command-line applications may not be particularly intuitive or exciting.
Being able to see and interact with your code is far more natural.
Building graphical applications can help the student connect the code they are writing to the real world.
After all, most non-programmers primarily interact with software that has a graphical interface of some sort.</p>
   <p>But why does this need to be in the standard?
There are, of course, many high-quality 3rd party C++ libraries that provide these features.
But, C++ also lacks a standard build system, packing system and a centralized source of packages.
This can make it notably more difficult to start using, say, a 3rd party 2D drawing library in C++.</p>
   <p>A common criticism of C++ is that the C++'s standard library is not as rich as the core libraries of other languages such as Java, Python, Javascript, Rust, Swift, etc.
But is the answer to that to try and standardize everything?
Many languages with diverse library ecosystems have them because they have package management; we do not.</p>
   <p>We believe it is questionable if the proposed drawing interface actually facilitates teaching.
Let’s consider an example.
Suppose you are teaching a group of teenagers with no programming experience and you want to change that.
There are a number of common starting points, but let’s use the one that is likely most popular: building a simple game.</p>
   <p>Suppose we want our students to start by building a simple animation (later, we’ll add keyboard input in to make it a game) where a single character moves around on a screen.</p>
   <p>Where do we start?</p>
   <ul>
    <li data-md="">
     <p>First, they need to get a window, and a surface in that window that they can draw in.</p>
    <li data-md="">
     <p>Then, they need to programmatically place the character on the screen at some starting position. The character could be represented as an instance of a class type, whose constructor puts it in the starting position,</p>
    <li data-md="">
     <p>Next, they’ll want to move the character around by programmatically updating its position and redrawing the screen. This could be done by adding methods to the character class: <code class="highlight"><span class="n">move_left</span></code>, <code class="highlight"><span class="n">move_right</span></code>, <code class="highlight"><span class="n">move_up</span></code>, <code class="highlight"><span class="n">move_down</span></code>, etc.</p>
   </ul>
   <p>Eventually, we’d want to replace the static animation with movement based on keyboard input.
Then we would add other game entities (other characters, obstacles, etc) and game logic for how they would interact.</p>
   <p>What we’re doing in this curriculum is <strong>teaching programming in C++ using graphics</strong>.</p>
   <p>This is not something that the proposed 2D drawing interface enables. <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a> gives you a mechanism to <strong>programmatically draw graphics using C++</strong>.
For example, you could programmatically draw the character in the above example.</p>
   <p>But, why would you want to have students do this?
The drawing of the character is not what we want to focus on; instead we want to build application logic that programmatically manipulates different objects (<strong>assets</strong>) on a surface.
Instead of drawing assets programmatically in C++, we could have the students use an image editing tool to create an image (JPG, SVG, etc) to use as their art asset.</p>
   <p>Drawing even simple images with a programmatic drawing interface will be verbose, and thus distracting from the core curriculum.
If one was to design a curriculum around this proposal, students would have to learn a lot about computer graphics in addition to C++.
Our goal is for students to learn C++ programming; graphics should be a teaching aid, not the main focus.</p>
   <p>We question whether a drawing library would be a useful teaching aid.
A simple facility for building graphical interfaces that supports and leverages established graphics standards and formats would allow programmers to use common image editing tools to generate art assets instead of having to express them programmatically in C++.</p>
   <h3 class="heading settled" data-level="3.2" id="enabling-graphics-programming"><span class="secno">3.2. </span><span class="content">Enabling Graphics Programming</span><a class="self-link" href="#enabling-graphics-programming"></a></h3>
   <p>There are two classes of graphics programmers:</p>
   <ul>
    <li data-md="">
     <p><strong>Graphical Application Developers (Not Always Experts)</strong> build graphics applications, such as games. They are mainly concerned with developing application logic that manipulates graphics asset but they do not typically programmatically build their assets with lower-level drawing interfaces. The assets they work with are developed in common formats such as Postscript or SVG by either the graphical application developers, artists that they collaborate with, asset banks, etc.</p>
    <li data-md="">
     <p><strong>Graphical Framework Developers (Experts)</strong> build graphics frameworks, engines, and libraries that graphical application developers use.</p>
   </ul>
   <p>Naturally, there are many more graphical application developers than there are framework developers.</p>
   <h4 class="heading settled" data-level="3.2.1" id="graphical-application-developers"><span class="secno">3.2.1. </span><span class="content">Graphical Application Developers</span><a class="self-link" href="#graphical-application-developers"></a></h4>
   <p>Graphical application developers are application programmers who build (usually interactive) software which displays visual output.
Some examples include games, cartography software, and scientific visualization.
Most graphical application developers do not regularly produce the art assets they use programmatically.
Instead, they consume assets produces upstream by artists, taken from asset banks, etc.</p>
   <p>A common concern when graphical application developers decide which APIs to use is what their <strong>asset toolchain</strong> will be - e.g. what tools will generate or what sources will provide the art content.
Graphical application programmers are going to be inclined to use APIs that don’t require explicit conversion, or worse - require them to write the conversion code themselves.</p>
   <p>Programmers developing graphical applications have many excellent options in 3rd party libraries, many of which have far greater capabilities than <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a>.
What would attract them to <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a> over the established alternatives?</p>
   <h4 class="heading settled" data-level="3.2.2" id="graphical-framework-developers"><span class="secno">3.2.2. </span><span class="content">Graphical Framework Developers</span><a class="self-link" href="#graphical-framework-developers"></a></h4>
   <p>Now let’s talk about the expert graphics programmers who are building graphics libraries and frameworks, which graphical application developers use.
Those graphical application developers want to pass the assets they created in existing established formats, such as Postscript or SVG.
For the frameworks to use the current proposed API, they would have to convert those assets to the <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a> path representation.
This would be unnecessary and inefficient, because the lower level APIs that <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a> would be built on top of probably support those formats natively.
Additionally, since the proposed API is not as extensive as SVG or Postscript, some things will not be easily expressible with <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a>.
Suppose we create an asset in SVG using a type of arc that SVG natively supports but <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a> does not.
You would have to figure out how to map that primitive to the <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a> primitives.</p>
   <p>Some have suggested that professional graphics programmers would use the proposed 2D drawing library.
Based on the author’s collective knowledge of the graphics community, we strongly believe this statement is not true.
Game/computer vision/visualization/etc developers are not going to use the proposed library. <strong>Graphics has its own standards, and graphics programmers don’t want us to make another one.</strong></p>
   <h2 class="heading settled" data-level="4" id="design-issues"><span class="secno">4. </span><span class="content">Design Issues</span><a class="self-link" href="#design-issues"></a></h2>
   <p>This section describes a number of high-level, broad technical concerns with <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a>.
This list is not comprehensive.</p>
   <h3 class="heading settled" data-level="4.1" id="lack-of-batching-operations"><span class="secno">4.1. </span><span class="content">Lack of Batching Operations</span><a class="self-link" href="#lack-of-batching-operations"></a></h3>
   <p>The current design of the library severely limits implementation options.
Essentially, due to the lack of a true batching API, the current design cannot efficiently utilize GPUs.</p>
   <p>GPUs are, fundamentally, bandwidth-optimized processors, while CPUs are latency-optimized processors.
Additionally, CPU to GPU communication typically has much greater latency than communication between threads and processes that reside on a single CPU (or even on between multiple CPUs within a single system).</p>
   <p>The key to efficient utilization of a GPU is to minimize the frequency of communication between the CPU and GPU and to maximize the size of the task given to the GPU by the CPU in each communication.</p>
   <p>This pushes GPU programming towards bulk/batched interfaces.
The latency cost of dispatching a single work item is high, so dispatching multiple work items in a single dispatch is desirable as it amortizes the cost.</p>
   <p>Modern 2D graphics libraries typically provide fully batched interfaces, which
allow a programmer to describe an entire scene (paths, strokes, fills, etc) in
a data structure and then hand it off in a single dispatch.</p>
   <p>The current design of the library does not follow this trend.
There is a mechanism for buffering paths, <code class="highlight"><span class="n">path_builder</span></code>, but this is not
sufficient as there is no mechanism for buffering strokes, fills, etc.</p>
   <p>For example, if I wanted to draw two figures, each with a different brush, I have no way of expressing this as single buffered rendering command:</p>
<pre class="highlight"><span class="k">auto</span> <span class="n">sfc</span> <span class="o">=</span> <span class="n">make_image_surface</span><span class="p">(</span><span class="n">format</span><span class="o">::</span><span class="n">rgb32</span><span class="p">,</span> <span class="mi">1024</span><span class="p">,</span> <span class="mi">1024</span><span class="p">);</span>

<span class="n">path_builder</span> <span class="n">pb0</span><span class="p">{};</span>

<span class="n">pb0</span><span class="p">.</span><span class="n">new_figure</span><span class="p">({</span> <span class="mf">20.0f</span><span class="p">,</span> <span class="mf">20.0f</span> <span class="p">});</span>
<span class="n">pb0</span><span class="p">.</span><span class="n">line</span><span class="p">({</span> <span class="mf">100.0f</span><span class="p">,</span> <span class="mf">20.0f</span> <span class="p">});</span>
<span class="n">pb0</span><span class="p">.</span><span class="n">line</span><span class="p">({</span> <span class="mf">20.0f</span><span class="p">,</span> <span class="mf">100.0f</span> <span class="p">});</span>
<span class="n">pb0</span><span class="p">.</span><span class="n">close_figure</span><span class="p">();</span>

<span class="c1">// Render</span>
<span class="c1"></span><span class="n">sfc</span><span class="p">.</span><span class="n">stroke</span><span class="p">(</span><span class="n">brush_a</span><span class="p">,</span> <span class="n">pb</span><span class="p">,</span> <span class="n">nullopt</span><span class="p">,</span> <span class="n">stroke_props</span><span class="p">{</span> <span class="mf">10.0f</span> <span class="p">},</span> <span class="n">nullopt</span><span class="p">,</span> <span class="n">aliased</span><span class="p">);</span>

<span class="n">path_builder</span> <span class="n">pb1</span><span class="p">{};</span>

<span class="n">pb1</span><span class="p">.</span><span class="n">new_figure</span><span class="p">({</span> <span class="mf">20.0f</span><span class="p">,</span> <span class="mf">20.0f</span> <span class="p">});</span>
<span class="n">pb0</span><span class="p">.</span><span class="n">line</span><span class="p">({</span> <span class="mf">20.0f</span><span class="p">,</span> <span class="mf">100.0f</span> <span class="p">});</span>
<span class="n">pb0</span><span class="p">.</span><span class="n">line</span><span class="p">({</span> <span class="mf">100.0f</span><span class="p">,</span> <span class="mf">20.0f</span> <span class="p">});</span>
<span class="n">pb1</span><span class="p">.</span><span class="n">close_figure</span><span class="p">();</span>

<span class="c1">// Render</span>
<span class="c1"></span><span class="n">sfc</span><span class="p">.</span><span class="n">stroke</span><span class="p">(</span><span class="n">brush_b</span><span class="p">,</span> <span class="n">pb</span><span class="p">,</span> <span class="n">nullopt</span><span class="p">,</span> <span class="n">stroke_props</span><span class="p">{</span> <span class="mf">10.0f</span> <span class="p">},</span> <span class="n">nullopt</span><span class="p">,</span> <span class="n">aliased</span><span class="p">);</span>
</pre>
   <p>P0267r7’s current model will largely prevent an efficient GPU implementation.</p>
   <h3 class="heading settled" data-level="4.2" id="text-and-unicode"><span class="secno">4.2. </span><span class="content">Text and Unicode</span><a class="self-link" href="#text-and-unicode"></a></h3>
   <p>In <a data-link-type="biblio" href="#biblio-n3791">[N3791]</a>, the paper that began work on the proposed drawing library, it was stated that the library should be able to draw text.</p>
   <p>The current proposal, <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a>, has a section on text rendering and display.
The section in it’s entirety is reproduced below:</p>
   <blockquote>
    <p>[ <em>Note:</em> Text rendering and matters related to it, such as font support, will be added at a later date. This section is a placeholder. The integration of text rendering is expected to result in the addition of member functions to the surface class and changes to other parts of the text. — end note ]</p>
   </blockquote>
   <p>Why is this feature missing from the library?
This component of the library would depend on the standardization of a text library with Unicode support.
There is work ongoing in this space, but it has not yet reached maturity.</p>
   <p>How much value and utility is there in producing a drawing library that cannot draw text?</p>
   <h3 class="heading settled" data-level="4.3" id="geometry-and-linear-algebra-types"><span class="secno">4.3. </span><span class="content">Geometry and Linear Algebra Types</span><a class="self-link" href="#geometry-and-linear-algebra-types"></a></h3>
   <p><a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a> proposes a number of geometry and linear algebra primitives, such as:</p>
   <ul>
    <li data-md="">
     <p><code class="highlight"><span class="n">basic_point_2d</span></code>, a 2D point type whose element type is <code class="highlight"><span class="kt">float</span></code>.</p>
    <li data-md="">
     <p><code class="highlight"><span class="n">basic_matrix_2d</span></code>, which represents three by three matrices, whose element type is <code class="highlight"><span class="kt">float</span></code>.</p>
    <li data-md="">
     <p><code class="highlight"><span class="n">basic_bounding_box</span></code>, which represents a rectangular space, whose element type is <code class="highlight"><span class="kt">float</span></code>.</p>
    <li data-md="">
     <p><code class="highlight"><span class="n">basic_circle</span></code>, which represents a circle, whose element type is <code class="highlight"><span class="kt">float</span></code>.</p>
   </ul>
   <p>These abstractions are far more general than 2D drawing.
Why are they being designed in this paper, and why are they being designed specifically for 2D drawing?
Why do they have a specific element type instead of being parameterized on element type?
Adopting these types is likely to lead to inconsistencies and pain down the road.</p>
   <p><code class="highlight"><span class="n">basic_point_2d</span></code> is specified to have a specific number of dimensions (2) and a specific element type (<code class="highlight"><span class="kt">float</span></code>).
Even within the field of 2D graphics, this seems unnecessarily specific.
Other proposals in flight have introduced general purpose integer point types with arbitrary dimensionality (<a data-link-type="biblio" href="#biblio-p0009r5">[P0009r5]</a>).</p>
   <p>Likewise, <code class="highlight"><span class="n">basic_matrix_2d</span></code> is not a generic linear algebra type, but instead a 2D matrix of a prescribed size, layout and element type.
Instead of having an indexing operator or method that takes an index as a parameter, this type an individual method for accessing each element (<code class="highlight"><span class="n">m00</span></code>, <code class="highlight"><span class="n">m01</span></code>, etc).
Without a <code class="highlight"><span class="k">operator</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span></code> or <code class="highlight"><span class="n">get</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span></code>, indexing with a runtime value is difficult.
If <code class="highlight"><span class="n">basic_matrix_2d</span></code> was considered in a vacuum, we do not believe it would pass muster for standardization.
This very specific type is likely not generic or robust enough for even the domain of 2D vector graphics, much less the wider community.</p>
   <p><code class="highlight"><span class="n">basic_bounding_box</span></code> and <code class="highlight"><span class="n">basic_circle</span></code> likewise suffer from a lack of genericity.</p>
   <p>This is not generally how we design library facilities.
Other domains that care about multi-dimensional coordinate types and linear algebra would be better served if we spent time designing generic, general purpose facilities in an effort independent of 2D drawing, but aware of its requirements.</p>
   <p>Before we spend additional time standardizing these dependencies of <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a>, perhaps we should consider whether that time would be better spent standardizing general purpose facilities that a 2D drawing library could be built on top of.</p>
   <h3 class="heading settled" data-level="4.4" id="new-container-type"><span class="secno">4.4. </span><span class="content">New Container Type</span><a class="self-link" href="#new-container-type"></a></h3>
   <p><a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a> proposes a new container type, <code class="highlight"><span class="n">basic_path_builder</span></code> (roughly equivalent to a <code class="highlight"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="k">typename</span> <span class="n">basic_figure_items</span><span class="o">&lt;</span><span class="n">GraphicsSurface</span><span class="o">>::</span><span class="n">figure_item</span><span class="o">></span></code>)  which seem unnecessary.
The interface of this type is largely additive on top of <code class="highlight"><span class="n">vector</span></code>.</p>
   <p>The need and justification for a new container type is unclear, as is the need to constrain users to storing sequences of figure items in a particular container type.
Generic algorithms that operate on iterators (or ranges) of figure items would be a far more flexible design.</p>
   <h2 class="heading settled" data-level="5" id="priorities"><span class="secno">5. </span><span class="content">Priorities</span><a class="self-link" href="#priorities"></a></h2>
   <h3 class="heading settled" data-level="5.1" id="committee-resources-are-limited"><span class="secno">5.1. </span><span class="content">Committee Resources are Limited</span><a class="self-link" href="#committee-resources-are-limited"></a></h3>
   <p>An unfortunate reality of our work is that committee resources and time are finite.
Thus, we must prioritize and even discard proposals either explicitly, or implicitly by never giving them time. <a href="https://wg21.link/P0393r0">Directions for ISO C++</a> attempts to describes how that sorting and prioritizing should happen.</p>
   <p>We must consider whether spending additional time on this proposal is the right investment for us.
In its current form, the proposal, which is limited to drawing shapes, is about 150 pages long.
It’s one of the largest proposals currently in flight. <a data-link-type="biblio" href="#biblio-n3791">[N3791]</a>, the paper which initiated work on a graphics proposal, stated that this feature should "ship in two years". <strong>That was in 2013.</strong></p>
   <p>We should be mindful of the sunk cost fallacy.
The proposal is still in LEWG and it seems clear that it needs additional time there before it advances, as there are many existing technical issues, some of which are detailed above.
Both at the Jacksonville 2018 meeting during the LEWG discussion of this proposal and during subsequent discussions, committee members with experience sitting in LWG estimated that it would take the equivalent of an entire meeting of LWG’s time to get the proposal out for a Technical Specification. 
Assuming that estimate is roughly accurate, it indicates a substantial resource investment.
We only have nine meetings in between each International Standard.
Approximately two to three of those meetings get spent on ballot resolution, leaving about six meetings for feature development. <strong>Are we comfortable spending 1/6th of the time that LWG would spend on an International Standard development cycle to get this feature into a Technical Specification?</strong></p>
   <p>There are many important library facilities that are currently missing from C++ which have greater and broader utility, such as ranges, networking, executors, text, unicode.
A number of those have been discussed in this proposal, as a drawing library depends on having these features.</p>
   <p>The committee is increasingly backlogged these days.
The reality, as pointed out in <a href="https://wg21.link/P0393r0">Directions for ISO C++</a>, is that we must evaluate and prioritize how we spend our time.
It is not "free" for us to continue investing time on <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a>.
In fact, quite the opposite; it comes with a great cost, even if the end goal is just a Technical Specification.</p>
   <p>Given that:</p>
   <ul>
    <li data-md="">
     <p>there are no clear users or demand for this feature from the community,</p>
    <li data-md="">
     <p>there is higher impact work that a 2D drawing library depends on,</p>
    <li data-md="">
     <p>there is higher impact work in general, and</p>
    <li data-md="">
     <p>the committee does not have infinite time,</p>
   </ul>
   <p>we believe that we should not continue pursuing <a data-link-type="biblio" href="#biblio-p0267r7">[P0267r7]</a>.</p>
   <h3 class="heading settled" data-level="5.2" id="what-belongs-in-the-standard"><span class="secno">5.2. </span><span class="content">What Belongs in The Standard?</span><a class="self-link" href="#what-belongs-in-the-standard"></a></h3>
   <p>The C++ Standard Library is not a library.
The C++ Standard is, well, a standard; a normative document that describes in the
most detailed and unambiguous way possible a universal and portable programming language implemented by many different vendors on a vast and varied set of platforms and used by ~5 million programmers.
The C++ Standard Library is not a library; it is a specification for a library.</p>
   <p>The bar for entry should be high.
The things that go into the C++ Standard should be cross-cutting across multiple domains within our community.
We should seek to standardize best practices and the things that would be terribly inconvenient to live anywhere but the standard.
The features we put into the C++ Standard should be be implementable across all modern platforms by all the vendors within our ecosystem, within reason.</p>
   <p>What should, or should not be included in the C++ standard library is a very important question.</p>
   <ul>
    <li data-md="">
     <p>Containers?</p>
    <li data-md="">
     <p>Filesystem Access?</p>
    <li data-md="">
     <p>Networking?</p>
    <li data-md="">
     <p>Unicode?</p>
    <li data-md="">
     <p>JSON?</p>
    <li data-md="">
     <p>XML?</p>
    <li data-md="">
     <p>Database Access?</p>
    <li data-md="">
     <p>Serialization?</p>
    <li data-md="">
     <p>2D Graphics?</p>
    <li data-md="">
     <p>3D Graphics?</p>
    <li data-md="">
     <p>Crypto?</p>
   </ul>
   <p>At some point, we need to draw a line.
What things are fundamental and absolutely need to work everywhere?
Those are the things that need to go in.</p>
   <p>Some have suggested that the proposed 2D drawing Technical Specification could remain as just that - a Technical Specification.
Technical Specifications do not necessarily need to eventually be merged into the International Standard.
But, we have to be aware of the risk of segmenting the language (which would be harmful to the community) by creating a multitude of Technical Specifications that are not intended for unification with the International Standard.
Technical Specifications are not a substitute for a package management system that has a principled approach to managing prerequisites and dependencies.</p>
   <p>Speaking of package management...
There many high quality C++ 2D graphics libraries out there.
Why aren’t they good enough?</p>
   <p>Perhaps 2D graphics isn’t the problem, but a symptom of a larger problem.
We are all aware - or should be - that one of the major pain points of C++ programming today is package management. <a href="https://isocpp.org/files/papers/CppDevSurvey-2018-02-summary.pdf">This was one of the leading responses from the C++ developer survey</a>.</p>
   <p>If the C++ community had a first class solution for package management - something with widespread adoption by users and implementers - would we be thinking about putting a 2D drawing library into the C++ Standard?</p>
   <p>As the C++ committee, package management may well be outside of our scope and mandate.
As leaders of the C++ community, it certainly is not.</p>
   <h2 class="heading settled" data-level="6" id="suggestions"><span class="secno">6. </span><span class="content">Suggestions</span><a class="self-link" href="#suggestions"></a></h2>
   <ul>
    <li data-md="">
     <p><strong>The C++ committee should not pursue a programmatic 2D drawing library at this time.</strong></p>
    <li data-md="">
     <p><strong>Text, Unicode, geometry and linear algebra libraries are prerequisites of a 2D drawing library that seem reasonable to consider for standardization.</strong></p>
    <li data-md="">
     <p><strong>We, the leaders of the C++ community, need to get serious about package management (not necessarily within the confines of standard).</strong></p>
   </ul>
   <h2 class="heading settled" data-level="7" id="alternative-minimal-graphics"><span class="secno">7. </span><span class="content">Alternative Minimal Graphics</span><a class="self-link" href="#alternative-minimal-graphics"></a></h2>
   <p>If the committee feels strongly that we want prioritize a <strong>minimal</strong> 2D vector graphics library that:</p>
   <ul>
    <li data-md="">
     <p>Gives you a portable way to get a window</p>
    <li data-md="">
     <p>Loads assets in an established vector graphics format</p>
    <li data-md="">
     <p>Draws them on a surface in the window</p>
   </ul>
   <p>We suggest the following minimal design and thin interface:</p>
<pre class="highlight"><span class="k">namespace</span> <span class="n">std</span><span class="o">::</span><span class="n">graphics</span> <span class="p">{</span>

  <span class="k">struct</span> <span class="n">display_exception</span><span class="p">;</span>

  <span class="k">struct</span> <span class="n">asset</span> <span class="p">{</span>
    <span class="k">explicit</span> <span class="n">asset</span><span class="p">(</span><span class="n">string</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">xml</span><span class="p">);</span>
    <span class="k">explicit</span> <span class="nf">asset</span><span class="p">(</span><span class="n">filesystem</span><span class="o">::</span><span class="n">path</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">file</span><span class="p">);</span>
    <span class="o">~</span><span class="n">asset</span><span class="p">();</span>
  <span class="p">};</span>

  <span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">Function</span><span class="o">></span>
  <span class="k">static</span> <span class="kt">void</span> <span class="n">process_events</span><span class="p">(</span><span class="kt">double</span> <span class="n">timeout</span><span class="p">,</span> <span class="n">Function</span> <span class="n">f</span><span class="p">);</span>

  <span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">></span>
  <span class="k">struct</span> <span class="n">point</span> <span class="p">{</span> <span class="n">T</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">;</span> <span class="p">};</span>

  <span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">></span>
  <span class="k">struct</span> <span class="n">rectangle</span> <span class="p">{</span> <span class="n">point</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span> <span class="n">top_left</span><span class="p">,</span> <span class="n">bottom_right</span><span class="p">;</span> <span class="p">};</span>

  <span class="k">struct</span> <span class="n">surface</span> <span class="p">{</span>
    <span class="kt">void</span> <span class="n">clear</span><span class="p">();</span>
    <span class="kt">void</span> <span class="nf">apply</span><span class="p">(</span><span class="n">asset</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">a</span><span class="p">,</span> <span class="n">rectangle</span><span class="o">&lt;</span><span class="kt">float</span><span class="o">></span> <span class="cm">/*window subrect*/</span><span class="p">);</span>
  <span class="p">};</span>

  <span class="k">struct</span> <span class="n">window</span> <span class="p">{</span>
    <span class="n">window</span><span class="p">(</span><span class="n">rectangle</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span> <span class="n">rect</span> <span class="o">=</span> <span class="p">{},</span> <span class="n">string</span> <span class="k">const</span><span class="o">&amp;</span> <span class="n">title</span> <span class="o">=</span> <span class="s">""</span><span class="p">);</span>
    <span class="o">~</span><span class="n">window</span><span class="p">();</span>

    <span class="kt">void</span> <span class="nf">on_key_down</span><span class="p">(</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">(</span><span class="kt">int</span> <span class="cm">/*key code*/</span><span class="p">)</span><span class="o">></span> <span class="n">action</span><span class="p">);</span>
    <span class="kt">void</span> <span class="nf">on_key_up</span><span class="p">(</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">(</span><span class="kt">int</span> <span class="cm">/*key code*/</span><span class="p">)</span><span class="o">></span> <span class="n">action</span><span class="p">);</span>
    <span class="kt">void</span> <span class="nf">on_pointer_pos</span><span class="p">(</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">(</span><span class="kt">float</span> <span class="cm">/*normalized x*/</span><span class="p">,</span> <span class="kt">float</span> <span class="cm">/*normalized y*/</span><span class="p">)</span><span class="o">></span> <span class="n">action</span><span class="p">);</span>
    <span class="kt">void</span> <span class="nf">on_pointer_down</span><span class="p">(</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">(</span><span class="kt">int</span> <span class="cm">/*button code*/</span><span class="p">)</span><span class="o">></span> <span class="n">action</span><span class="p">);</span>
    <span class="kt">void</span> <span class="nf">on_pointer_up</span><span class="p">(</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">(</span><span class="kt">int</span> <span class="cm">/*button code*/</span><span class="p">)</span><span class="o">></span> <span class="n">action</span><span class="p">);</span>

    <span class="kt">void</span> <span class="nf">on_draw</span><span class="p">(</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">(</span><span class="n">surface</span><span class="o">&amp;</span><span class="cm">/*render target*/</span><span class="p">)</span><span class="o">></span> <span class="n">action</span><span class="p">);</span>
    <span class="kt">void</span> <span class="nf">on_close</span><span class="p">(</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">()</span><span class="o">></span> <span class="n">action</span><span class="p">);</span>
    <span class="kt">void</span> <span class="nf">on_place</span><span class="p">(</span><span class="n">function</span><span class="o">&lt;</span><span class="kt">void</span><span class="p">(</span><span class="n">rectangle</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span><span class="cm">/*display subrect*/</span><span class="p">)</span><span class="o">></span> <span class="n">action</span><span class="p">);</span>

    <span class="kt">void</span> <span class="nf">place</span><span class="p">(</span><span class="n">rectangle</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span> <span class="n">rect</span><span class="p">);</span>
    <span class="kt">void</span> <span class="nf">redraw</span><span class="p">();</span>
    <span class="kt">bool</span> <span class="nf">closed</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>

    <span class="k">using</span> <span class="n">native_handle_type</span> <span class="o">=</span> <span class="n">implementation</span><span class="o">-</span><span class="n">defined</span><span class="p">;</span>
    <span class="n">native_handle_type</span> <span class="nf">native_handle</span><span class="p">();</span>
  <span class="p">};</span>

<span class="p">}</span>
</pre>
   <p>Objects of class <code class="highlight"><span class="n">asset</span></code> encapsulate a vector or raster asset: a W3C SVG graph, a PNG image, etc. Constructors are provided that consume strings (W3C SVG graph format, etc) and files (textual representation of a graph in the W3C SVG XML format, binary PNG content, etc). Much like objects of class <code class="highlight"><span class="n">regex</span></code>, these can be parsed once and used often, to amortize the cost of constructing the graph. [ Note: Objects of class <code class="highlight"><span class="n">asset</span></code> are akin to figures. – End note ] [ Note: Implementations may define additional asset formats. – End note ]</p>
   <p>The free function <code class="highlight"><span class="n">process_events</span></code> shall be invoked in the main thread, and repeatedly executes the following steps:
1.) Blocks waiting for the next window event, or until <code class="highlight"><span class="n">timeout</span></code> seconds have elapsed.
2.) Processes all available window events.
3.) Invokes <code class="highlight"><span class="n">f</span></code>, it shall be <code class="highlight"><span class="n">Callable</span></code> with no arguments and return <code class="highlight"><span class="kt">bool</span></code>.
4.) If <code class="highlight"><span class="n">f</span></code> returned false, <code class="highlight"><span class="n">process_events</span></code> returns.</p>
   <p>Objects of class <code class="highlight"><span class="n">window</span></code> encapsulate implementation-defined display windows. A display window is user-visible rectangular grid of pixels that can be the target of user interaction events, such typing, pointing, moving, resizing and closing.</p>
   <p>The constructor <code class="highlight"><span class="n">window</span><span class="o">::</span><span class="n">window</span></code> creates a visible display window with suggested screen footprint <code class="highlight"><span class="n">rect</span></code> in pixels, and suggested name title. Implementations should ensure that these parameters are respected, if possible. The member functions have the following semantics:</p>
   <ul>
    <li data-md="">
     <p>The member functions <code class="highlight"><span class="n">window</span><span class="o">::</span><span class="n">on_</span><span class="o">*</span></code> set the event handler for different event. Each takes a <code class="highlight"><span class="n">Callable</span></code> operand that replaces the previous handler, if any. [ <em>Note:</em> The only way to draw on a display window is by registering a handler with <code class="highlight"><span class="n">on_draw</span></code>, in order to get access to a surface object. – <em>end note</em> ]</p>
    <li data-md="">
     <p>The member function <code class="highlight"><span class="n">window</span><span class="o">::</span><span class="n">place</span></code> raises a place event on the window, with suggested screen footprint <code class="highlight"><span class="n">rect</span></code>.</p>
    <li data-md="">
     <p>The member function <code class="highlight"><span class="n">window</span><span class="o">::</span><span class="n">redraw</span></code> raises a draw event on the window. [ <em>Note:</em> This causes the handler registered with <code class="highlight"><span class="n">on_draw</span></code> to eventually execute. – <em>end note</em> ]</p>
    <li data-md="">
     <p>The member function <code class="highlight"><span class="n">window</span><span class="o">::</span><span class="n">closed</span></code> returns true if the display window has been closed.</p>
    <li data-md="">
     <p>The member function <code class="highlight"><span class="n">window</span><span class="o">::</span><span class="n">native_handle</span></code> returns an object of type <code class="highlight"><span class="n">native_handle_type</span></code> suitable for use with implementation-defined capabilities, such as advanced rendering capabilities. Implementations may require that no operation to the display window be performed through the <code class="highlight"><span class="n">native_handle</span></code> once any operation has been performed through a <code class="highlight"><span class="n">surface</span></code> object.</p>
   </ul>
   <p>Objects of class <code class="highlight"><span class="n">surface</span></code> encapsulate the rendering capabilities of a display window. A display window may only render objects of class <code class="highlight"><span class="n">asset</span></code>, and only as an effect of executing a function registered with on_draw. A surface presents only two operations:</p>
   <ul>
    <li data-md="">
     <p>The member function <code class="highlight"><span class="n">surface</span><span class="o">::</span><span class="n">clear</span></code> invalidates the contents of the display window. The meaning of this operation is implementation-defined.</p>
    <li data-md="">
     <p>The member function <code class="highlight"><span class="n">surface</span><span class="o">::</span><span class="n">apply</span></code> renders an object of class asset with relative footprint <code class="highlight"><span class="n">rect</span></code>.</p>
   </ul>
   <p>An example:</p>
<pre class="highlight"><span class="cp">#include</span> &lt;graphics><span class="cp"></span>
<span class="cp"></span>
<span class="k">template</span><span class="o">&lt;</span><span class="k">class</span> <span class="nc">T</span><span class="o">></span>
<span class="k">using</span> <span class="n">rectangle</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">graphics</span><span class="o">::</span><span class="n">rectangle</span><span class="o">&lt;</span><span class="n">T</span><span class="o">></span><span class="p">;</span>
<span class="k">using</span> <span class="n">asset</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">graphics</span><span class="o">::</span><span class="n">asset</span><span class="p">;</span>
<span class="k">using</span> <span class="n">window</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">graphics</span><span class="o">::</span><span class="n">window</span><span class="p">;</span>
<span class="k">using</span> <span class="n">surface</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">graphics</span><span class="o">::</span><span class="n">surface</span><span class="p">;</span>

<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>

  <span class="n">window</span> <span class="n">w</span><span class="p">(</span><span class="n">rectangle</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">></span><span class="p">{{</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">},{</span><span class="mi">600</span><span class="p">,</span><span class="mi">600</span><span class="p">}});</span>

  <span class="n">asset</span> <span class="k">const</span> <span class="n">a</span><span class="p">{</span> <span class="n">my_asset_string_here</span> <span class="p">};</span>
  <span class="n">w</span><span class="p">.</span><span class="n">on_draw</span><span class="p">([</span><span class="o">&amp;</span><span class="p">](</span><span class="n">surface</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
    <span class="n">s</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
    <span class="n">s</span><span class="p">.</span><span class="n">apply</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">rectangle</span><span class="o">&lt;</span><span class="kt">float</span><span class="o">></span><span class="p">{{</span><span class="mf">0.f</span><span class="p">,</span><span class="mf">0.f</span><span class="p">},{</span><span class="mf">1.f</span><span class="p">,</span><span class="mf">1.f</span><span class="p">}});</span>
  <span class="p">});</span>
  <span class="n">window</span><span class="o">::</span><span class="n">process_events</span><span class="p">(</span><span class="mf">1.</span><span class="o">/</span><span class="mi">60</span><span class="p">,</span> <span class="p">[</span><span class="o">&amp;</span><span class="p">](){</span>
    <span class="k">if</span> <span class="p">(</span><span class="n">w</span><span class="p">.</span><span class="n">closed</span><span class="p">())</span>
      <span class="k">return</span> false<span class="p">;</span>
    <span class="n">w</span><span class="p">.</span><span class="n">redraw</span><span class="p">();</span>
    <span class="k">return</span> true<span class="p">;</span>
  <span class="p">});</span>
<span class="p">}</span>
</pre>
  </main>
<script>
(function() {
  "use strict";
  var collapseSidebarText = '<span aria-hidden="true">←</span> '
                          + '<span>Collapse Sidebar</span>';
  var expandSidebarText   = '<span aria-hidden="true">→</span> '
                          + '<span>Pop Out Sidebar</span>';
  var tocJumpText         = '<span aria-hidden="true">↑</span> '
                          + '<span>Jump to Table of Contents</span>';

  var sidebarMedia = window.matchMedia('screen and (min-width: 78em)');
  var autoToggle   = function(e){ toggleSidebar(e.matches) };
  if(sidebarMedia.addListener) {
    sidebarMedia.addListener(autoToggle);
  }

  function toggleSidebar(on) {
    if (on == undefined) {
      on = !document.body.classList.contains('toc-sidebar');
    }

    /* Don’t scroll to compensate for the ToC if we’re above it already. */
    var headY = 0;
    var head = document.querySelector('.head');
    if (head) {
      // terrible approx of "top of ToC"
      headY += head.offsetTop + head.offsetHeight;
    }
    var skipScroll = window.scrollY < headY;

    var toggle = document.getElementById('toc-toggle');
    var tocNav = document.getElementById('toc');
    if (on) {
      var tocHeight = tocNav.offsetHeight;
      document.body.classList.add('toc-sidebar');
      document.body.classList.remove('toc-inline');
      toggle.innerHTML = collapseSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, 0 - tocHeight);
      }
      tocNav.focus();
      sidebarMedia.addListener(autoToggle); // auto-collapse when out of room
    }
    else {
      document.body.classList.add('toc-inline');
      document.body.classList.remove('toc-sidebar');
      toggle.innerHTML = expandSidebarText;
      if (!skipScroll) {
        window.scrollBy(0, tocNav.offsetHeight);
      }
      if (toggle.matches(':hover')) {
        /* Unfocus button when not using keyboard navigation,
           because I don’t know where else to send the focus. */
        toggle.blur();
      }
    }
  }

  function createSidebarToggle() {
    /* Create the sidebar toggle in JS; it shouldn’t exist when JS is off. */
    var toggle = document.createElement('a');
      /* This should probably be a button, but appearance isn’t standards-track.*/
    toggle.id = 'toc-toggle';
    toggle.class = 'toc-toggle';
    toggle.href = '#toc';
    toggle.innerHTML = collapseSidebarText;

    sidebarMedia.addListener(autoToggle);
    var toggler = function(e) {
      e.preventDefault();
      sidebarMedia.removeListener(autoToggle); // persist explicit off states
      toggleSidebar();
      return false;
    }
    toggle.addEventListener('click', toggler, false);


    /* Get <nav id=toc-nav>, or make it if we don’t have one. */
    var tocNav = document.getElementById('toc-nav');
    if (!tocNav) {
      tocNav = document.createElement('p');
      tocNav.id = 'toc-nav';
      /* Prepend for better keyboard navigation */
      document.body.insertBefore(tocNav, document.body.firstChild);
    }
    /* While we’re at it, make sure we have a Jump to Toc link. */
    var tocJump = document.getElementById('toc-jump');
    if (!tocJump) {
      tocJump = document.createElement('a');
      tocJump.id = 'toc-jump';
      tocJump.href = '#toc';
      tocJump.innerHTML = tocJumpText;
      tocNav.appendChild(tocJump);
    }

    tocNav.appendChild(toggle);
  }

  var toc = document.getElementById('toc');
  if (toc) {
    createSidebarToggle();
    toggleSidebar(sidebarMedia.matches);

    /* If the sidebar has been manually opened and is currently overlaying the text
       (window too small for the MQ to add the margin to body),
       then auto-close the sidebar once you click on something in there. */
    toc.addEventListener('click', function(e) {
      if(e.target.tagName.toLowerCase() == "a" && document.body.classList.contains('toc-sidebar') && !sidebarMedia.matches) {
        toggleSidebar(false);
      }
    }, false);
  }
  else {
    console.warn("Can’t find Table of Contents. Please use <nav id='toc'> around the ToC.");
  }

  /* Wrap tables in case they overflow */
  var tables = document.querySelectorAll(':not(.overlarge) > table.data, :not(.overlarge) > table.index');
  var numTables = tables.length;
  for (var i = 0; i < numTables; i++) {
    var table = tables[i];
    var wrapper = document.createElement('div');
    wrapper.className = 'overlarge';
    table.parentNode.insertBefore(wrapper, table);
    wrapper.appendChild(table);
  }

})();
</script>
  <h2 class="no-num no-ref heading settled" id="references"><span class="content">References</span><a class="self-link" href="#references"></a></h2>
  <h3 class="no-num no-ref heading settled" id="informative"><span class="content">Informative References</span><a class="self-link" href="#informative"></a></h3>
  <dl>
   <dt id="biblio-n3791">[N3791]
   <dd>Beman Dawes. <a href="https://wg21.link/n3791">Lightweight Drawing Library - Objectives, Requirements, Strategies</a>. 11 October 2013. URL: <a href="https://wg21.link/n3791">https://wg21.link/n3791</a>
   <dt id="biblio-p0009r5">[P0009r5]
   <dd>H. Carter Edwards, Daniel Sunderland, David Hollman, Christian Trott, Mauro Bianco, Ben Sander, Athanasios Iliopoulos, John Michopoulos. <a href="https://wg21.link/p0009r5">Polymorphic Multidimensional Array Reference</a>. URL: <a href="https://wg21.link/p0009r5">https://wg21.link/p0009r5</a>
   <dt id="biblio-p0267r7">[P0267r7]
   <dd>Michael B. McLaughlin, Herb Sutter, Jason Zink, Guy Davidson. <a href="https://wg21.link/p0267r7">A Proposal to Add 2D Graphics Rendering and Display to C++</a>. URL: <a href="https://wg21.link/p0267r7">https://wg21.link/p0267r7</a>
  </dl>