brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.5 KiB · 3dd5143 Raw
223 lines · cpp
1//===-- xray-graph.cpp: XRay Function Call Graph Renderer -----------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// A class to get a color from a specified gradient.10//11//===----------------------------------------------------------------------===//12 13#include "xray-color-helper.h"14#include "llvm/Support/FormatVariadic.h"15#include "llvm/Support/raw_ostream.h"16#include <cmath>17 18using namespace llvm;19using namespace xray;20 21//  Sequential ColorMaps, which are used to represent information22//  from some minimum to some maximum.23 24const std::tuple<uint8_t, uint8_t, uint8_t> SequentialMaps[][9] = {25    {// The greys color scheme from http://colorbrewer2.org/26     std::make_tuple(255, 255, 255), std::make_tuple(240, 240, 240),27     std::make_tuple(217, 217, 217), std::make_tuple(189, 189, 189),28     std::make_tuple(150, 150, 150), std::make_tuple(115, 115, 115),29     std::make_tuple(82, 82, 82), std::make_tuple(37, 37, 37),30     std::make_tuple(0, 0, 0)},31    {// The OrRd color scheme from http://colorbrewer2.org/32     std::make_tuple(255, 247, 236), std::make_tuple(254, 232, 200),33     std::make_tuple(253, 212, 158), std::make_tuple(253, 187, 132),34     std::make_tuple(252, 141, 89), std::make_tuple(239, 101, 72),35     std::make_tuple(215, 48, 31), std::make_tuple(179, 0, 0),36     std::make_tuple(127, 0, 0)},37    {// The PuBu color scheme from http://colorbrewer2.org/38     std::make_tuple(255, 247, 251), std::make_tuple(236, 231, 242),39     std::make_tuple(208, 209, 230), std::make_tuple(166, 189, 219),40     std::make_tuple(116, 169, 207), std::make_tuple(54, 144, 192),41     std::make_tuple(5, 112, 176), std::make_tuple(4, 90, 141),42     std::make_tuple(2, 56, 88)}};43 44// Sequential Maps extend the last colors given out of range inputs.45const std::tuple<uint8_t, uint8_t, uint8_t> SequentialBounds[][2] = {46    {// The Bounds for the greys color scheme47     std::make_tuple(255, 255, 255), std::make_tuple(0, 0, 0)},48    {// The Bounds for the OrRd color Scheme49     std::make_tuple(255, 247, 236), std::make_tuple(127, 0, 0)},50    {// The Bounds for the PuBu color Scheme51     std::make_tuple(255, 247, 251), std::make_tuple(2, 56, 88)}};52 53ColorHelper::ColorHelper(ColorHelper::SequentialScheme S)54    : MinIn(0.0), MaxIn(1.0), ColorMap(SequentialMaps[static_cast<int>(S)]),55      BoundMap(SequentialBounds[static_cast<int>(S)]) {}56 57// Diverging ColorMaps, which are used to represent information58// representing differenes, or a range that goes from negative to positive.59// These take an input in the range [-1,1].60 61const std::tuple<uint8_t, uint8_t, uint8_t> DivergingCoeffs[][11] = {62    {// The PiYG color scheme from http://colorbrewer2.org/63     std::make_tuple(142, 1, 82), std::make_tuple(197, 27, 125),64     std::make_tuple(222, 119, 174), std::make_tuple(241, 182, 218),65     std::make_tuple(253, 224, 239), std::make_tuple(247, 247, 247),66     std::make_tuple(230, 245, 208), std::make_tuple(184, 225, 134),67     std::make_tuple(127, 188, 65), std::make_tuple(77, 146, 33),68     std::make_tuple(39, 100, 25)}};69 70// Diverging maps use out of bounds ranges to show missing data. Missing Right71// Being below min, and missing left being above max.72const std::tuple<uint8_t, uint8_t, uint8_t> DivergingBounds[][2] = {73    {// The PiYG color scheme has green and red for missing right and left74     // respectively.75     std::make_tuple(255, 0, 0), std::make_tuple(0, 255, 0)}};76 77ColorHelper::ColorHelper(ColorHelper::DivergingScheme S)78    : MinIn(-1.0), MaxIn(1.0), ColorMap(DivergingCoeffs[static_cast<int>(S)]),79      BoundMap(DivergingBounds[static_cast<int>(S)]) {}80 81// Takes a tuple of uint8_ts representing a color in RGB and converts them to82// HSV represented by a tuple of doubles83static std::tuple<double, double, double>84convertToHSV(const std::tuple<uint8_t, uint8_t, uint8_t> &Color) {85  double Scaled[3] = {std::get<0>(Color) / 255.0, std::get<1>(Color) / 255.0,86                      std::get<2>(Color) / 255.0};87  int Min = 0;88  int Max = 0;89  for (int i = 1; i < 3; ++i) {90    if (Scaled[i] < Scaled[Min])91      Min = i;92    if (Scaled[i] > Scaled[Max])93      Max = i;94  }95 96  double C = Scaled[Max] - Scaled[Min];97 98  double HPrime =99      (C == 0) ? 0 : (Scaled[(Max + 1) % 3] - Scaled[(Max + 2) % 3]) / C;100  HPrime = HPrime + 2.0 * Max;101 102  double H = (HPrime < 0) ? (HPrime + 6.0) * 60103                          : HPrime * 60; // Scale to between 0 and 360104  double V = Scaled[Max];105 106  double S = (V == 0.0) ? 0.0 : C / V;107 108  return std::make_tuple(H, S, V);109}110 111// Takes a double precision number, clips it between 0 and 1 and then converts112// that to an integer between 0x00 and 0xFF with proxpper rounding.113static uint8_t unitIntervalTo8BitChar(double B) {114  double n = std::clamp(B, 0.0, 1.0);115  return static_cast<uint8_t>(255 * n + 0.5);116}117 118// Takes a typle of doubles representing a color in HSV and converts them to119// RGB represented as a tuple of uint8_ts120static std::tuple<uint8_t, uint8_t, uint8_t>121convertToRGB(const std::tuple<double, double, double> &Color) {122  const double &H = std::get<0>(Color);123  const double &S = std::get<1>(Color);124  const double &V = std::get<2>(Color);125 126  double C = V * S;127 128  double HPrime = H / 60;129  double X = C * (1 - std::abs(std::fmod(HPrime, 2.0) - 1));130 131  double RGB1[3];132  int HPrimeInt = static_cast<int>(HPrime);133  if (HPrimeInt % 2 == 0) {134    RGB1[(HPrimeInt / 2) % 3] = C;135    RGB1[(HPrimeInt / 2 + 1) % 3] = X;136    RGB1[(HPrimeInt / 2 + 2) % 3] = 0.0;137  } else {138    RGB1[(HPrimeInt / 2) % 3] = X;139    RGB1[(HPrimeInt / 2 + 1) % 3] = C;140    RGB1[(HPrimeInt / 2 + 2) % 3] = 0.0;141  }142 143  double Min = V - C;144  double RGB2[3] = {RGB1[0] + Min, RGB1[1] + Min, RGB1[2] + Min};145 146  return std::make_tuple(unitIntervalTo8BitChar(RGB2[0]),147                         unitIntervalTo8BitChar(RGB2[1]),148                         unitIntervalTo8BitChar(RGB2[2]));149}150 151// The Hue component of the HSV interpolation Routine152static double interpolateHue(double H0, double H1, double T) {153  double D = H1 - H0;154  if (H0 > H1) {155    std::swap(H0, H1);156 157    D = -D;158    T = 1 - T;159  }160 161  if (D <= 180) {162    return H0 + T * (H1 - H0);163  } else {164    H0 = H0 + 360;165    return std::fmod(H0 + T * (H1 - H0) + 720, 360);166  }167}168 169// Interpolates between two HSV Colors both represented as a tuple of doubles170// Returns an HSV Color represented as a tuple of doubles171static std::tuple<double, double, double>172interpolateHSV(const std::tuple<double, double, double> &C0,173               const std::tuple<double, double, double> &C1, double T) {174  double H = interpolateHue(std::get<0>(C0), std::get<0>(C1), T);175  double S = std::get<1>(C0) + T * (std::get<1>(C1) - std::get<1>(C0));176  double V = std::get<2>(C0) + T * (std::get<2>(C1) - std::get<2>(C0));177  return std::make_tuple(H, S, V);178}179 180// Get the Color as a tuple of uint8_ts181std::tuple<uint8_t, uint8_t, uint8_t>182ColorHelper::getColorTuple(double Point) const {183  assert(!ColorMap.empty() && "ColorMap must not be empty!");184  assert(!BoundMap.empty() && "BoundMap must not be empty!");185 186  if (Point < MinIn)187    return BoundMap[0];188  if (Point > MaxIn)189    return BoundMap[1];190 191  size_t MaxIndex = ColorMap.size() - 1;192  double IntervalWidth = MaxIn - MinIn;193  double OffsetP = Point - MinIn;194  double SectionWidth = IntervalWidth / static_cast<double>(MaxIndex);195  size_t SectionNo = std::floor(OffsetP / SectionWidth);196  double T = (OffsetP - SectionNo * SectionWidth) / SectionWidth;197 198  auto &RGBColor0 = ColorMap[SectionNo];199  auto &RGBColor1 = ColorMap[std::min(SectionNo + 1, MaxIndex)];200 201  auto HSVColor0 = convertToHSV(RGBColor0);202  auto HSVColor1 = convertToHSV(RGBColor1);203 204  auto InterpolatedHSVColor = interpolateHSV(HSVColor0, HSVColor1, T);205  return convertToRGB(InterpolatedHSVColor);206}207 208// A helper method to convert a color represented as tuple of uint8s to a hex209// string.210std::string211ColorHelper::getColorString(std::tuple<uint8_t, uint8_t, uint8_t> t) {212  return std::string(llvm::formatv("#{0:X-2}{1:X-2}{2:X-2}", std::get<0>(t),213                                   std::get<1>(t), std::get<2>(t)));214}215 216// Gets a color in a gradient given a number in the interval [0,1], it does this217// by evaluating a polynomial which maps [0, 1] -> [0, 1] for each of the R G218// and B values in the color. It then converts this [0,1] colors to a 24 bit219// color as a hex string.220std::string ColorHelper::getColorString(double Point) const {221  return getColorString(getColorTuple(Point));222}223