Skip to content

Commit

Permalink
Merge pull request #58 from sergiomrebelo/semantics-measures
Browse files Browse the repository at this point in the history
Semantics measures
  • Loading branch information
sergiomrebelo authored Jan 22, 2024
2 parents 5f4e04f + 3f16ad3 commit 264874e
Show file tree
Hide file tree
Showing 17 changed files with 9,149 additions and 164 deletions.
3 changes: 2 additions & 1 deletion cypress/e2e/evolution.cy.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import 'cypress-wait-until';

const TESTING_EXAMPLES = [
{text: `Never Mind¶The Bollocks,¶Here's the¶Sex Pistols`}
{text: `Never Mind¶The Bollocks,¶Here's the¶Sex Pistols`},
{text: `The children¶almost broken¶by the world¶become the adults¶most likely¶to change it`}
]

// check if system is evolving
Expand Down
55 changes: 55 additions & 0 deletions evo-poster.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
const TYPEFACES = {
Amstelvar: {
leading: 1.05,
tags: [`serif`],
axes: [`wght`, `wdth`],
url: `https://github.com/googlefonts/amstelvar`
},
Anybody: {
leading: 1.05,
tags: [`sans-serif`, `90s`, `europe`],
axes: [`wght`, `wdth`],
url: `https://github.com/Etcetera-Type-Co/Anybody`,
},
Barlow: {
leading: 1.05,
tags: [`sans-serif`, `gothic`, `monoline`, `neo-grotesque`],
axes: [`wght`, `wdth`],
url: `https://tribby.com/fonts/barlow/`,
},
Cabin: {
leading: 1.05,
tags: [`sans-serif`, `gothic`, `soft-corners`],
axes: [`wght`],
url: `https://fonts.google.com/specimen/Cabin`,
},
Emberly: {
leading: 1.05,
tags: [`serif`, `didone`],
axes: [`wght`, `wdth`],
url: `https://www.behance.net/gallery/87667103/Emberly-Free-Typeface-54-Styles`,
},
Epilogue: {
leading: 1.05,
tags: [`sans-serif`],
axes: [`wght`, `wdth`],
url: `https://etceteratype.co/epilogue`,
},
IBMPlexSans: {
leading: 1.05,
tags: [`sans-serif`],
axes: [`wght`, `wdth`],
url: `https://fonts.google.com/specimen/IBM+Plex+Sans`,
},
Inconsolata: {
leading: 1.05,
tags: [`sans-serif`, `mono`],
axes: [`wght`, `wdth`],
url: `https://fonts.google.com/specimen/Inconsolata`,

}
}

export default {
typography: TYPEFACES !== undefined ? TYPEFACES : {}
}
2 changes: 1 addition & 1 deletion rollup.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export default [
dir: 'src/public',
name: 'version',
assetFileNames: 'assets/[name]-[hash][extname]',
plugins: [terser()],
plugins: [], //terser()
}
],
watch: {
Expand Down
37 changes: 37 additions & 0 deletions src/@evoposter/evaluator/semantics-visual.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
export default {
anger : {
color: {
typography: [`#ff0000`, `#00ff00`],
background: [`#ff0000`]
},
typefaces: [`sans-serif`, `neo-grotesque`]
},
joy: {
color: {
typography: [],
background: [`#ffff00`, `#00ff00`]
},
typefaces: [`sans-serif`, `serif`]
},
trust: {
color: {
typography: [],
background: [`#0000ff`, `#00ff00`]
},
typefaces: [`neo-grotesque`]
},
sadness: {
color: {
typography: [],
background: [`#0071b6`]
},
typefaces: []
},
disgust: {
color: {
typography: [`#800080`],
background: []
},
typefaces: []
}
}
11 changes: 11 additions & 0 deletions src/@evoposter/evaluator/src/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,23 @@

import * as Legibility from "./metrics/Legibility.mjs";
import * as GridAppropriateSize from "./metrics/GridAppropriateSize.mjs";
import * as SemanticsLayout from "./metrics/SemanticsLayout.mjs";
import * as SemanticsEmphasis from "./metrics/SemanticsEmphasis.mjs";
import * as SemanticsVisuals from "./metrics/SemanticVisuals.mjs";

export const info = () => {
console.log ("Evaluator working");
}

// constraints
export const legibility = Legibility.compute;
export const gridAppropriateSize = GridAppropriateSize.compute;

// semantics
export const semanticsLayout = SemanticsLayout.compute;
export const semanticsEmphasis = SemanticsEmphasis.compute;
export const semanticsVisuals = SemanticsVisuals.compute;

// aesthetics

export { info as default };
107 changes: 107 additions & 0 deletions src/@evoposter/evaluator/src/metrics/SemanticVisuals.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
/**
* Semantic Visuals Measure
*
* This function assesses the appropriateness of visual features (type design and colour)
* based on the emotions collected. It takes into account the configuration file "visual-semantics.config.js".
*
* The function returns the mean difference between all textboxes,
* yielding a value between 1 (good) and 0 (bad).
* If there is no information pertaining to a particular emotion, the value defaults to 1.
*
* As of now, the function exclusively considers the predominant emotions from ML analysis.
*
* Author: Sérgio M. Rebelo
* CDV lab. (CMS, CISUC, Portugal)
* Contact: srebelo[at]dei.uc.pt
*
* Version: 1.0.0 (November 2023)
*/

const MAX_COLOR_DISTANCE = 441.67;

import * as configurationFile from "../../semantics-visual.config.js";
import {arrMean, colorDistance, hexToRGB, constraint} from "../utils.js";


export const compute = async (data, textboxes, background, typefaceData, config = configurationFile) => {

let emotion = data.predominant.emotion;

if (config["default"][emotion] === undefined) return 1;

const targetTypefaceColors = config["default"][emotion]["color"]["typography"];
const targetBackgroundColors = config["default"][emotion]["color"]["background"];
const targetTypographyFeatures = config["default"][emotion]["typefaces"];

// typography colour
let meanTypefaceColorDistance = 1;
if (targetTypefaceColors !== undefined && targetTypefaceColors.length > 0) {
let typefaceColorsDistances = [];
for (let t of textboxes) {
let c = hexToRGB(t.color);
let typefaceColorsDist = Number.MAX_VALUE;
for (let targetColor of targetTypefaceColors) {
targetColor = hexToRGB(targetColor);
let distance = colorDistance(c, targetColor)
if (distance < typefaceColorsDist) {
typefaceColorsDist = distance;
}
}
typefaceColorsDistances.push(typefaceColorsDist);
}

meanTypefaceColorDistance = typefaceColorsDistances.length < 1 ? 1 : arrMean(typefaceColorsDistances);
meanTypefaceColorDistance /= MAX_COLOR_DISTANCE;
meanTypefaceColorDistance = constraint(1-meanTypefaceColorDistance, 0, 1);
}

// background colour
let meanTypefaceBackgroundDistance = 1;
if (targetBackgroundColors !== undefined && targetBackgroundColors.length !== 0) {
let backgroundColorsDistances = [];
meanTypefaceBackgroundDistance = 0;
for (let c of background) {
c = hexToRGB(c);
let backgroundColorsDist = Number.MAX_VALUE;
for (let targetColor of targetBackgroundColors) {
targetColor = hexToRGB(targetColor);
let distance = colorDistance(c, targetColor);
if (distance < backgroundColorsDist) {
backgroundColorsDist = distance;
}
}
backgroundColorsDistances.push(backgroundColorsDist);
}

meanTypefaceBackgroundDistance = meanTypefaceBackgroundDistance.length < 1 ? 1 : arrMean(backgroundColorsDistances);
meanTypefaceBackgroundDistance /= MAX_COLOR_DISTANCE;
meanTypefaceBackgroundDistance = constraint(1-meanTypefaceBackgroundDistance, 0, 1);
}

// typeface
let meanTypefaceError = 1;
if (targetTypographyFeatures !== undefined && targetTypographyFeatures.length > 0) {
let fontsTags = [];
for (let t of textboxes) {
let tbTagsValue = 0;
const typefaceIndex = typefaceData.map(t => t.family).indexOf(t["typeface"]);
const tags = typefaceData[typefaceIndex]["tags"];
for (let t of targetTypographyFeatures) {
if (tags.includes(t)) {
tbTagsValue += (1/targetTypographyFeatures.length)
}
}
fontsTags.push(tbTagsValue);
}

meanTypefaceError = fontsTags.length < 1 ? 1 : arrMean(fontsTags);
meanTypefaceError = constraint(meanTypefaceError, 0, 1);
}

return (meanTypefaceColorDistance + meanTypefaceBackgroundDistance + meanTypefaceError)/3;


}


export {compute as default};
Loading

0 comments on commit 264874e

Please sign in to comment.