| Author | DaveJarvis <email> |
|---|---|
| Date | 2020-07-20 23:04:55 GMT-0700 |
| Commit | 1f921dc8e1260eafe0a08f93aa30ce30920f04b7 |
| Parent | 8dbfba9 |
| import java.beans.PropertyChangeEvent; | ||
| import java.beans.PropertyChangeListener; | ||
| +import java.util.Map; | ||
| import static com.whitemagicsoftware.kmcaster.HardwareState.ANY_KEY; | ||
| import static java.awt.Font.BOLD; | ||
| import static java.lang.Boolean.FALSE; | ||
| +import static java.lang.Boolean.TRUE; | ||
| import static java.lang.Math.abs; | ||
| import static javax.swing.SwingConstants.CENTER; | ||
| */ | ||
| private static final Font LABEL_FONT = new Font( "DejaVu Sans", BOLD, 32 ); | ||
| + | ||
| + private static final String KEY_UP = FALSE.toString(); | ||
| + private static final String KEY_DOWN = TRUE.toString(); | ||
| /** | ||
| - * Matches the shift-key arrow font colour. | ||
| + * Matches the shift-key arrow font colour when pressed. | ||
| */ | ||
| - private static final Color LABEL_COLOUR = new Color( 33, 33, 33 ); | ||
| + private static final Color COLOUR_KEY_DN = new Color( 0x21, 0x21, 0x21 ); | ||
| + | ||
| + /** | ||
| + * Matches the shift-key arrow font colour when released. | ||
| + */ | ||
| + private static final Color COLOUR_KEY_UP = new Color( 0xE5, 0xE5, 0xE5 ); | ||
| + | ||
| + /** | ||
| + * Maps key pressed states to key cap title colours. | ||
| + */ | ||
| + private static final Map<String, Color> KEY_COLOURS = Map.of( | ||
| + KEY_DOWN, COLOUR_KEY_DN, | ||
| + KEY_UP, COLOUR_KEY_UP | ||
| + ); | ||
| private final HardwareImages mHardwareImages; | ||
| // released (doesn't matter what kind of key). | ||
| final var context = | ||
| - (!"false".equals( switchValue ) && !"true".equals( switchValue )) | ||
| + (!KEY_UP.equals( switchValue ) && !KEY_DOWN.equals( switchValue )) | ||
| ? ANY_KEY | ||
| : switchValue; | ||
| protected void updateSwitchLabel( | ||
| final HardwareState state, final String value ) { | ||
| - if( state.isModifier() ) { | ||
| -// final var label = new AutofitLabel( value, LABEL_FONT, LABEL_COLOUR ); | ||
| -// label.setVisible( false ); | ||
| - System.out.println( state.getHardwareSwitch().toTitleCase() ); | ||
| + final var container = getHardwareComponent( state ); | ||
| + | ||
| + if( KEY_UP.equals( value ) ) { | ||
| + container.removeAll(); | ||
| } | ||
| - else { | ||
| - final var container = getHardwareComponent( state ); | ||
| + | ||
| + if( state.isModifier() ) { | ||
| + final var hwSwitch = state.getHardwareSwitch(); | ||
| + final var switchName = hwSwitch.toTitleCase(); | ||
| + final var keyColour = KEY_COLOURS.get( value ); | ||
| + | ||
| + final var label = new AutofitLabel( switchName, LABEL_FONT, keyColour ); | ||
| + label.setVisible( false ); | ||
| + label.setHorizontalAlignment( CENTER ); | ||
| + label.setVerticalAlignment( CENTER ); | ||
| container.removeAll(); | ||
| + container.add( label ); | ||
| + label.setVisible( true ); | ||
| + } | ||
| + else if( !KEY_UP.equals( value ) ) { | ||
| + // A non-modifier key has been pressed. | ||
| + final var index = value.indexOf( ' ' ); | ||
| + final var keyColour = KEY_COLOURS.get( KEY_DOWN ); | ||
| - if( !FALSE.toString().equals( value ) ) { | ||
| - final var index = value.indexOf( ' ' ); | ||
| + // If there's a space in the name, the text before the space is | ||
| + // positioned in the upper-left while the text afterwards takes up | ||
| + // the remainder. This is used for number pad keys, backspace, enter, | ||
| + // tab, and a few others. | ||
| + if( index > 0 ) { | ||
| + final var calculator = new BoundsCalculator( container ); | ||
| + final var contDimen = new ScalableDimension( calculator.computeSize() ); | ||
| + final var supSize = contDimen.scale( .6f ); | ||
| + final var mainSize = contDimen.scale( .9f ); | ||
| - // If there's a space in the name, the text before the space is | ||
| - // positioned in the upper-left while the text afterwards takes up | ||
| - // the remainder. This is used for number pad keys, backspace, enter, | ||
| - // tab, and a few others. | ||
| - if( index > 0 ) { | ||
| - final var calculator = new BoundsCalculator( container ); | ||
| - final var bounds = calculator.computeSize(); | ||
| - final var containerDim = new ScalableDimension( bounds ); | ||
| + final var s = new String[]{ | ||
| + value.substring( 0, index ), | ||
| + value.substring( index + 1 ) | ||
| + }; | ||
| - final var s = new String[]{ | ||
| - value.substring( 0, index ), | ||
| - value.substring( index + 1 ) | ||
| - }; | ||
| + // Label for "Num", "Back", "Tab", and other dual-labelled keys. | ||
| + final var sup = new AutofitLabel( s[ 0 ], LABEL_FONT, keyColour ); | ||
| + sup.setVisible( false ); | ||
| + sup.setVerticalAlignment( TOP ); | ||
| - // "Num", "Back", "Tab", and other superscript contextual keys. | ||
| - final var sup = new AutofitLabel( s[ 0 ], LABEL_FONT, LABEL_COLOUR ); | ||
| - sup.setVisible( false ); | ||
| - container.add( sup ); | ||
| - sup.setVerticalAlignment( TOP ); | ||
| - sup.setSize( containerDim.scale( .6f ) ); | ||
| - sup.setVisible( true ); | ||
| + // Label for number pad keys or icon glyphs. | ||
| + final var main = new AutofitLabel( s[ 1 ], LABEL_FONT, keyColour ); | ||
| + main.setVisible( false ); | ||
| + main.setHorizontalAlignment( CENTER ); | ||
| + main.setVerticalAlignment( CENTER ); | ||
| - // Number pad keys or icon glyphs. | ||
| - final var main = new AutofitLabel( s[ 1 ], LABEL_FONT, LABEL_COLOUR ); | ||
| - main.setVisible( false ); | ||
| - container.add( main ); | ||
| - main.setSize( containerDim.scale( .9f ) ); | ||
| - main.setHorizontalAlignment( CENTER ); | ||
| - main.setVerticalAlignment( CENTER ); | ||
| + // Keep removing then adding as close together as possible to minimize | ||
| + // flicker. | ||
| + container.removeAll(); | ||
| + container.add( main ); | ||
| + container.add( sup ); | ||
| + main.setSize( mainSize ); | ||
| + sup.setSize( supSize ); | ||
| - // Center-align the main text with respect to the container. | ||
| - final var location = main.getLocation(); | ||
| - final var dx = abs( containerDim.getWidth() - main.getWidth() ) / 2; | ||
| - final var dy = abs( containerDim.getHeight() - main.getHeight() ) / 2; | ||
| + // Center-align the main text with respect to the container. | ||
| + final var location = main.getLocation(); | ||
| + final var dx = abs( contDimen.getWidth() - main.getWidth() ) / 2; | ||
| + final var dy = abs( contDimen.getHeight() - main.getHeight() ) / 2; | ||
| - // Shift the main text down a smidgen, relative to the superscript. | ||
| - main.setLocation( | ||
| - (int) (location.getX() + dx), | ||
| - (int) (location.getY() + dy) + sup.getHeight() / 4 ); | ||
| - main.setVisible( true ); | ||
| - } | ||
| - else { | ||
| - // Single keys need no tweaking and can be added to the container | ||
| - // directly. The horizontal and vertical alignments | ||
| - final var label = new AutofitLabel( value, LABEL_FONT, LABEL_COLOUR ); | ||
| - label.setVisible( false ); | ||
| - container.add( label ); | ||
| - label.setHorizontalAlignment( CENTER ); | ||
| - label.setVerticalAlignment( CENTER ); | ||
| - label.setVisible( true ); | ||
| - } | ||
| + // Shift the main text down a smidgen, relative to the superscript. | ||
| + main.setLocation( | ||
| + (int) (location.getX() + dx), | ||
| + (int) (location.getY() + dy) + sup.getHeight() / 4 ); | ||
| + main.setVisible( true ); | ||
| + sup.setVisible( true ); | ||
| + } | ||
| + else { | ||
| + // Single keys need no tweaking and can be added to the container | ||
| + // directly. The horizontal and vertical alignments | ||
| + final var label = new AutofitLabel( value, LABEL_FONT, keyColour ); | ||
| + label.setVisible( false ); | ||
| + label.setHorizontalAlignment( CENTER ); | ||
| + label.setVerticalAlignment( CENTER ); | ||
| + container.removeAll(); | ||
| + container.add( label ); | ||
| + label.setVisible( true ); | ||
| } | ||
| } | ||
| */ | ||
| public HardwareComponent( final Insets insets ) { | ||
| + setDoubleBuffered( true ); | ||
| mInsets = insets; | ||
| } |
| ); | ||
| + /** | ||
| + * Defines the amount of space between around the vector graphic projection | ||
| + * of a key. These values are specific to the projected sizes and must be | ||
| + * measured while editing the vector graphic (e.g., using the ruler tool), | ||
| + * rounded up then codified here. The insets will be scaled to fit the | ||
| + * application window frame. | ||
| + * <p> | ||
| + * The shift key insets offset the safe area to the right of the up arrow | ||
| + * icon. | ||
| + * </p> | ||
| + */ | ||
| + private final static Map<HardwareSwitch, Insets> SWITCH_INSETS = Map.of( | ||
| + KEY_ALT, new Insets( 8, 11, 12, 11 ), | ||
| + KEY_CTRL, new Insets( 8, 11, 12, 11 ), | ||
| + KEY_SHIFT, new Insets( 5, 50, 9, 11 ), | ||
| + KEY_REGULAR, new Insets( 3, 7, 6, 7 ) | ||
| + ); | ||
| + | ||
| private final static SvgRasterizer sRasterizer = new SvgRasterizer(); | ||
| final var imageUp = keyUpImage( FILE_NAME_PREFIXES.get( key ) ); | ||
| final var scale = imageDn.getValue(); | ||
| + final var insets = new KeyCapInsets( SWITCH_INSETS.get(key) ); | ||
| + final var scaledInsets = insets.scale( scale ); | ||
| - final var insets = KeyCapInsets.scale( scale ); | ||
| - final var hardwareComponent = createHardwareComponent( insets ); | ||
| + final var hardwareComponent = createHardwareComponent( scaledInsets ); | ||
| hardwareComponent.put( stateOn, imageDn.getKey() ); | ||
| * mouse images have neither insets nor padding. | ||
| */ | ||
| -public class KeyCapInsets { | ||
| - /** | ||
| - * Defines the amount of space between the 3D base of a key and the 3D | ||
| - * top of the key; the vector graphic is a 2D projection and these values | ||
| - * are specific to the projected sizes. | ||
| - */ | ||
| - private final static Insets INSET_PROJECTED = | ||
| - new Insets( 3, 7, 6, 7 ); | ||
| - | ||
| +public final class KeyCapInsets { | ||
| /** | ||
| * Defines the padding around the inside of the key cap to give the letters | ||
| * some whitespace. | ||
| */ | ||
| private final static Insets INSET_PADDING = | ||
| new Insets( 4, 4, 4, 4 ); | ||
| - private final static Insets INSET_TOTAL = | ||
| - new Insets( | ||
| - INSET_PROJECTED.top + INSET_PADDING.top, | ||
| - INSET_PROJECTED.left + INSET_PADDING.left, | ||
| - INSET_PROJECTED.bottom + INSET_PADDING.bottom, | ||
| - INSET_PROJECTED.right + INSET_PADDING.right | ||
| - ); | ||
| + /** | ||
| + * Includes safe zone and internal padding. | ||
| + */ | ||
| + private final Insets mInsets; | ||
| + | ||
| + /** | ||
| + * Creates a new area for drawing on a key cap. This class will add an | ||
| + * internal padding amount. | ||
| + * | ||
| + * @param insets The insets that correlate the "safe zone" for drawing | ||
| + * items on the key cap, without padding. | ||
| + */ | ||
| + public KeyCapInsets( final Insets insets ) { | ||
| + mInsets = new Insets( | ||
| + insets.top + INSET_PADDING.top, | ||
| + insets.left + INSET_PADDING.left, | ||
| + insets.bottom + INSET_PADDING.bottom, | ||
| + insets.right + INSET_PADDING.right | ||
| + ); | ||
| + } | ||
| /** | ||
| * Scales the image insets and padding. | ||
| */ | ||
| - public static Insets scale( final DimensionTuple factor ) { | ||
| + public Insets scale( final DimensionTuple factor ) { | ||
| final var wRatio = factor.getWidthRatio(); | ||
| final var hRatio = factor.getHeightRatio(); | ||
| return new Insets( | ||
| - (int) (INSET_TOTAL.top * hRatio), | ||
| - (int) (INSET_TOTAL.left * wRatio), | ||
| - (int) (INSET_TOTAL.bottom * hRatio), | ||
| - (int) (INSET_TOTAL.right * wRatio) ); | ||
| + (int) (mInsets.top * hRatio), | ||
| + (int) (mInsets.left * wRatio), | ||
| + (int) (mInsets.bottom * hRatio), | ||
| + (int) (mInsets.right * wRatio) ); | ||
| } | ||
| } |
| public AutofitLabel( final String text, final Font font, final Color color ) { | ||
| super( text ); | ||
| + setDoubleBuffered( true ); | ||
| setFont( font ); | ||
| setForeground( color ); |
| -<svg height="60" viewBox="0 0 37.042 15.875" width="140" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(-.060888 0 0 .060336 56.497 -18.194)" gradientUnits="userSpaceOnUse" x1="338.63" x2="358.68" y1="522.48" y2="538.13"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><linearGradient id="b" gradientTransform="matrix(.36493 0 0 .36162 -33.305 -67.568)" gradientUnits="userSpaceOnUse" x1="93.499" x2="97.32" y1="223.35" y2="225.96"><stop offset="0" stop-color="#656565"/><stop offset="1" stop-color="#939393"/></linearGradient><linearGradient id="c" gradientTransform="matrix(.36493 0 0 .36162 -33.305 -67.568)" gradientUnits="userSpaceOnUse" x1="186.6" x2="186.1" y1="190.18" y2="188.08"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><linearGradient id="d" gradientTransform="matrix(.36493 0 0 .36162 -33.344 -67.568)" gradientUnits="userSpaceOnUse" x1="127.4" x2="167.04" y1="207.21" y2="207.21"><stop offset="0" stop-color="#d8d8d8"/><stop offset="1" stop-color="#b1b1b1"/></linearGradient><linearGradient id="e" gradientTransform="matrix(.36493 0 0 .36162 -33.344 -67.568)" gradientUnits="userSpaceOnUse" x1="97.58" x2="128.18" y1="202.35" y2="202.35"><stop offset="0" stop-color="#f1f1f1"/><stop offset="1" stop-color="#c1c1c1"/></linearGradient><g fill-rule="evenodd" stroke-width=".36327"><path d="m.84701 0h33.741c.46924 0 .84701.37434.84701.83932v10.724h-35.423l-.011539-10.724c-.0005474-.46498.37776-.83932.847-.83932z" fill="#656565"/><path d="m2.5208 13.795h31.832v2.0735h-31.832z" fill="#929292"/><path d="m32.91 1.1636h4.1317l.000004 10.408h-4.1317z" fill="#d6d6d6"/><path d="m33.878 11.228 3.1637.34396-.000004 3.0387c-.0015.78594-.63212 1.2375-1.2839 1.2647l-1.4053-.007-1.5509-3.5889z" fill="url(#a)"/><path d="m2.195 11.197-2.1835.36569-.011539 3.0474c.0016422.78594.63212 1.2375 1.2839 1.2647l1.4031-.01522.49205-3.5655z" fill="url(#b)"/><path d="m34.389 2.0256 2.653-.86194c-.10539-.82869-.6792-1.1252-1.4787-1.1421-.20536-.0043395-.37419-.01602-.59203-.019672-.21784-.0036886-.71487-.00035801-.71487-.00035801-.50121.097262-.89355.38179-1.1678.84836z" fill="url(#c)"/></g><rect fill="url(#d)" fill-rule="evenodd" height="12.812" ry=".97192" stroke="url(#e)" stroke-width=".26459" width="32.55" x="2.246" y=".95721"/><path d="m4.3714 7.7022h2.4614v2.8001h3.0769v-2.8024h2.4616l-4-3.4159z" fill="none" stroke="#333" stroke-width=".77404"/></svg> | ||
| +<svg height="60" viewBox="0 0 37.042 15.875" width="140" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(-.060888 0 0 .060336 56.497 -18.194)" gradientUnits="userSpaceOnUse" x1="338.63" x2="358.68" y1="522.48" y2="538.13"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><linearGradient id="b" gradientTransform="matrix(.36493 0 0 .36162 -33.305 -67.568)" gradientUnits="userSpaceOnUse" x1="93.499" x2="97.32" y1="223.35" y2="225.96"><stop offset="0" stop-color="#656565"/><stop offset="1" stop-color="#939393"/></linearGradient><linearGradient id="c" gradientTransform="matrix(.36493 0 0 .36162 -33.305 -67.568)" gradientUnits="userSpaceOnUse" x1="186.6" x2="186.1" y1="190.18" y2="188.08"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><linearGradient id="d" gradientTransform="matrix(.36493 0 0 .36162 -33.344 -67.568)" gradientUnits="userSpaceOnUse" x1="127.4" x2="167.04" y1="207.21" y2="207.21"><stop offset="0" stop-color="#d8d8d8"/><stop offset="1" stop-color="#b1b1b1"/></linearGradient><linearGradient id="e" gradientTransform="matrix(.36493 0 0 .36162 -33.344 -67.568)" gradientUnits="userSpaceOnUse" x1="97.58" x2="128.18" y1="202.35" y2="202.35"><stop offset="0" stop-color="#f1f1f1"/><stop offset="1" stop-color="#c1c1c1"/></linearGradient><g fill-rule="evenodd" stroke-width=".36327"><path d="m.84701 0h33.741c.46924 0 .84701.37434.84701.83932v10.724h-35.423l-.011539-10.724c-.0005474-.46498.37776-.83932.847-.83932z" fill="#656565"/><path d="m2.5208 13.795h31.832v2.0735h-31.832z" fill="#929292"/><path d="m32.91 1.1636h4.1317l.000004 10.408h-4.1317z" fill="#d6d6d6"/><path d="m33.878 11.228 3.1637.34396-.000004 3.0387c-.0015.78594-.63212 1.2375-1.2839 1.2647l-1.4053-.007-1.5509-3.5889z" fill="url(#a)"/><path d="m2.195 11.197-2.1835.36569-.011539 3.0474c.0016422.78594.63212 1.2375 1.2839 1.2647l1.4031-.01522.49205-3.5655z" fill="url(#b)"/><path d="m34.389 2.0256 2.653-.86194c-.10539-.82869-.6792-1.1252-1.4787-1.1421-.20536-.0043395-.37419-.01602-.59203-.019672-.21784-.0036886-.71487-.00035801-.71487-.00035801-.50121.097262-.89355.38179-1.1678.84836z" fill="url(#c)"/></g><rect fill="url(#d)" fill-rule="evenodd" height="12.812" ry=".97192" stroke="url(#e)" stroke-width=".26459" width="32.55" x="2.246" y=".95721"/><path d="m4.482 7.7355h2.4519v2.8124h3.065v-2.8147h2.4521l-3.9845-3.4309z" fill="none" stroke="#333" stroke-width=".77424"/></svg> |
| - | ||
| +<svg height="60" viewBox="0 0 37.042 15.875" width="140" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(-.060888 0 0 .060336 56.497 -18.194)" gradientUnits="userSpaceOnUse" x1="338.63" x2="358.68" y1="522.48" y2="538.13"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#939393"/></linearGradient><linearGradient id="b" gradientTransform="matrix(.36493 0 0 .36162 -33.305 -67.568)" gradientUnits="userSpaceOnUse" x1="93.499" x2="97.32" y1="223.35" y2="225.96"><stop offset="0" stop-color="#656565"/><stop offset="1" stop-color="#939393"/></linearGradient><linearGradient id="c" gradientTransform="matrix(.36493 0 0 .36162 -33.305 -67.568)" gradientUnits="userSpaceOnUse" x1="186.6" x2="186.1" y1="190.18" y2="188.08"><stop offset="0" stop-color="#d6d6d6"/><stop offset="1" stop-color="#656565"/></linearGradient><linearGradient id="d" gradientTransform="matrix(.36493 0 0 .36162 -33.344 -67.568)" gradientUnits="userSpaceOnUse" x1="127.4" x2="167.04" y1="207.21" y2="207.21"><stop offset="0" stop-color="#d8d8d8"/><stop offset="1" stop-color="#b1b1b1"/></linearGradient><linearGradient id="e" gradientTransform="matrix(.36493 0 0 .36162 -33.344 -67.568)" gradientUnits="userSpaceOnUse" x1="97.58" x2="128.18" y1="202.35" y2="202.35"><stop offset="0" stop-color="#f1f1f1"/><stop offset="1" stop-color="#c1c1c1"/></linearGradient><g fill-rule="evenodd" stroke-width=".36327"><path d="m.84701 0h33.741c.46924 0 .84701.37434.84701.83932v10.724h-35.423l-.011539-10.724c-.0005474-.46498.37776-.83932.847-.83932z" fill="#656565"/><path d="m2.5208 13.795h31.832v2.0735h-31.832z" fill="#929292"/><path d="m32.91 1.1636h4.1317l.000004 10.408h-4.1317z" fill="#d6d6d6"/><path d="m33.878 11.228 3.1637.34396-.000004 3.0387c-.0015.78594-.63212 1.2375-1.2839 1.2647l-1.4053-.007-1.5509-3.5889z" fill="url(#a)"/><path d="m2.195 11.197-2.1835.36569-.011539 3.0474c.0016422.78594.63212 1.2375 1.2839 1.2647l1.4031-.01522.49205-3.5655z" fill="url(#b)"/><path d="m34.389 2.0256 2.653-.86194c-.10539-.82869-.6792-1.1252-1.4787-1.1421-.20536-.0043395-.37419-.01602-.59203-.019672-.21784-.0036886-.71487-.00035801-.71487-.00035801-.50121.097262-.89355.38179-1.1678.84836z" fill="url(#c)"/></g><rect fill="url(#d)" fill-rule="evenodd" height="12.812" ry=".97192" stroke="url(#e)" stroke-width=".26459" width="32.55" x="2.246" y=".95721"/><path d="m4.482 7.7355h2.4519v2.8124h3.065v-2.8147h2.4521l-3.9845-3.4309z" fill="none" stroke="#333" stroke-width=".77424"/></svg> |
| -<svg height="60" viewBox="0 0 37.042 15.875" width="140" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(.36493 0 0 .36162 -33.344 -67.568)" gradientUnits="userSpaceOnUse" x1="97.58" x2="128.18" y1="202.35" y2="202.35"><stop offset="0" stop-color="#fafafa"/><stop offset="1" stop-color="#f1f1f1"/></linearGradient><g fill="#e5e5e5" fill-rule="evenodd" stroke-width=".36327"><path d="m.84701 0h33.741c.46924 0 .84701.37434.84701.83932v10.724h-35.423l-.011539-10.724c-.0005474-.46498.37776-.83932.847-.83932z"/><path d="m2.5208 13.795h31.832v2.0735h-31.832z"/><path d="m32.91 1.1636h4.1317l.000004 10.408h-4.1317z"/><path d="m33.878 11.228 3.1637.34396-.000004 3.0387c-.0015.78594-.63212 1.2375-1.2839 1.2647l-1.4053-.007-1.5509-3.5889z"/><path d="m2.195 11.197-2.1835.36569-.011539 3.0474c.0016422.78594.63212 1.2375 1.2839 1.2647l1.4031-.01522.49205-3.5655z"/><path d="m34.389 2.0256 2.653-.86194c-.10539-.82869-.6792-1.1252-1.4787-1.1421-.20536-.0043395-.37419-.01602-.59203-.019672-.21784-.0036886-.71487-.00035801-.71487-.00035801-.50121.097262-.89355.38179-1.1678.84836z"/></g><rect fill="#f8f8f8" fill-rule="evenodd" height="12.812" ry=".97192" stroke="url(#a)" stroke-width=".26459" width="32.55" x="2.246" y=".95721"/><path d="m4.3714 7.7022h2.4614v2.8001h3.0769v-2.8024h2.4616l-4-3.4159z" fill="none" stroke="#e5e5e5" stroke-width=".77404"/></svg> | ||
| +<svg height="60" viewBox="0 0 37.042 15.875" width="140" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><linearGradient id="a" gradientTransform="matrix(.36493 0 0 .36162 -33.344 -67.568)" gradientUnits="userSpaceOnUse" x1="97.58" x2="128.18" y1="202.35" y2="202.35"><stop offset="0" stop-color="#fafafa"/><stop offset="1" stop-color="#f1f1f1"/></linearGradient><g fill="#e5e5e5" fill-rule="evenodd" stroke-width=".36327"><path d="m.84701 0h33.741c.46924 0 .84701.37434.84701.83932v10.724h-35.423l-.011539-10.724c-.0005474-.46498.37776-.83932.847-.83932z"/><path d="m2.5208 13.795h31.832v2.0735h-31.832z"/><path d="m32.91 1.1636h4.1317l.000004 10.408h-4.1317z"/><path d="m33.878 11.228 3.1637.34396-.000004 3.0387c-.0015.78594-.63212 1.2375-1.2839 1.2647l-1.4053-.007-1.5509-3.5889z"/><path d="m2.195 11.197-2.1835.36569-.011539 3.0474c.0016422.78594.63212 1.2375 1.2839 1.2647l1.4031-.01522.49205-3.5655z"/><path d="m34.389 2.0256 2.653-.86194c-.10539-.82869-.6792-1.1252-1.4787-1.1421-.20536-.0043395-.37419-.01602-.59203-.019672-.21784-.0036886-.71487-.00035801-.71487-.00035801-.50121.097262-.89355.38179-1.1678.84836z"/></g><rect fill="#f8f8f8" fill-rule="evenodd" height="12.812" ry=".97192" stroke="url(#a)" stroke-width=".26459" width="32.55" x="2.246" y=".95721"/><path d="m4.482 7.7355h2.4519v2.8124h3.065v-2.8147h2.4521l-3.9845-3.4309z" fill="none" stroke="#e5e5e5" stroke-width=".77424"/></svg> |
| Delta | 144 lines added, 83 lines removed, 61-line increase |
|---|