#include <LovyanGFX.hpp>

static LGFX lcd;

void drawGradation(void)
{
  // 在背景上绘制渐变
  lcd.startWrite();
  lcd.setAddrWindow(0, 0, lcd.width(), lcd.height());
  for (int y = 0; y < lcd.height(); ++y) {
    for (int x = 0; x < lcd.width(); ++x) {
      lcd.writeColor(lcd.color888(x>>1, (x + y) >> 2, y>>1), 1);
    }
  }
  lcd.endWrite();
}

void setup(void)
{
  lcd.init();

  drawGradation();

  // 文字绘制方法大致分为两种：print系列函数和drawString系列函数。

  // drawString函数中，第一个参数指定字符串，第二个参数指定X坐标，第三个参数指定Y坐标。
  lcd.drawString("string!", 10, 10);

  // drawNumber函数中，第一个参数是数值。
  lcd.drawNumber(123, 100, 10);

  // drawFloat函数中，第一个参数是数值，第二个参数是小数点后的位数，第三个参数是X坐标，第四个参数是Y坐标。
  lcd.drawFloat(3.14, 2, 150, 10);

  // print函数在setCursor函数指定的坐标（或print函数最后绘制的字符的继续位置）进行绘制。
  lcd.setCursor(10, 20);
  lcd.print("print!");

  // printf函数可以绘制第二个参数及之后的内容。（遵循C语言的printf，因此可以绘制字符串和浮点数）
  int value = 123;
  lcd.printf("test %d", value);

  // println函数可以在绘制字符串后换行。与print("\n");效果相同。
  lcd.println("println");

  // 要更改字体，请使用setFont函数。
  // 与TFT_eSPI的setTextFont函数相同的字体是Font0～Font8。
  // ※如果可以使用编辑器的输入辅助，在参数中输入&fonts::即可显示字体列表
  lcd.setFont(&fonts::Font4);
  lcd.println("TestFont4");

  // 为了与TFT_eSPI兼容，也支持通过setTextFont函数按编号更改字体。
  // 可以指定的数字是0、2、4、6、7、8。（遵循TFT_eSPI）
  // ※但是，这种方法会强制将其他编号的字体也包含在二进制中，导致文件大小膨胀，因此不推荐。
  lcd.setTextFont(2);
  lcd.println("TestFont2");


  // 使用setTextColor可以更改颜色。
  // 第一个参数是文字颜色，第二个参数是背景颜色。
  lcd.setTextColor(0x00FFFFU, 0xFF0000U);
  lcd.print("CyanText RedBack");
  // ※如果想在同一位置重复绘制文字，建议指定背景颜色进行覆盖绘制。
  //    如果使用fillRect等清除后再重绘，可能会发生闪烁。


  // 在setTextColor中仅指定第一个参数而省略第二个参数时，
  // 将只绘制文字而不填充背景。
  lcd.setTextColor(0xFFFF00U);
  lcd.print("YellowText ClearBack");


  // Font6只包含时钟用的文字。
  lcd.setFont(&fonts::Font6);
  lcd.print("apm.:-0369");

  // Font7包含7段液晶风格的字体。
  lcd.setFont(&fonts::Font7);
  lcd.print(".:-147");

  // Font8只包含数字。
  lcd.setFont(&fonts::Font8);
  lcd.print(".:-258");


  delay(3000);
  drawGradation();

// 预设了4种×9尺寸=36种由IPA字体转换的日文字体。
// 末尾的数字表示大小，有8、12、16、20、24、28、32、36、40可用。
// fonts::lgfxJapanMincho_12      // 明朝体 大小16 固定宽度字体
// fonts::lgfxJapanMinchoP_16     // 明朝体 大小16 比例字体
// fonts::lgfxJapanGothic_20      // 黑体 大小20 固定宽度字体
// fonts::lgfxJapanGothicP_24     // 黑体 大小24 比例字体

// 预设了由efont转换的日语、韩语、中文（简体字、繁体字）字体各4种×5大小=20种。
// 数字表示大小，有10、12、14、16、24可用。
// 末尾的字符表示b=粗体 / i=斜体。
// fonts::efontJA_10              // 日语 大小10
// fonts::efontCN_12_b            // 简体字 大小12 粗体
// fonts::efontTW_14_bi           // 繁体字 大小14 粗体斜体
// fonts::efontKR_16_i            // 韩语 大小16 斜体

  lcd.setCursor(0, 0);
  lcd.setFont(&fonts::lgfxJapanMincho_16);   lcd.print("明朝体 16 Hello World\nこんにちは世界\n");
//lcd.setFont(&fonts::lgfxJapanMinchoP_16);  lcd.print("明朝 P 16 Hello World\nこんにちは世界\n");
  lcd.setFont(&fonts::lgfxJapanGothic_16);   lcd.print("ゴシック体 16 Hello World\nこんにちは世界\n");
//lcd.setFont(&fonts::lgfxJapanGothicP_16);  lcd.print("ゴシック P 16 Hello World\nこんにちは世界\n");

// ※使用山猫氏的[日语字体子集生成器](https://github.com/yamamaya/lgfxFontSubsetGenerator)
//   可以创建只包含必要字符的小尺寸字体数据。


  delay(3000);
  drawGradation();


  // 在LovyanGFX中，也可以使用setFont函数使用AdafruitGFX字体。
  // （为了与TFT_eSPI兼容，也准备了setFreeFont函数）
  lcd.setFont(&fonts::FreeSerif9pt7b);


  // 如果想右对齐或居中对齐绘制，请使用setTextDatum函数指定基准位置。
  // 垂直方向有top、middle、baseline、bottom四种，水平方向有left、center、right三种。
  // 从垂直和水平指定的组合中的12种中选择。
  lcd.setTextDatum( textdatum_t::top_left        );
  lcd.setTextDatum( textdatum_t::top_center      );
  lcd.setTextDatum( textdatum_t::top_right       );
  lcd.setTextDatum( textdatum_t::middle_left     );
  lcd.setTextDatum( textdatum_t::middle_center   );
  lcd.setTextDatum( textdatum_t::middle_right    );
  lcd.setTextDatum( textdatum_t::baseline_left   );
  lcd.setTextDatum( textdatum_t::baseline_center );
  lcd.setTextDatum( textdatum_t::baseline_right  );
  lcd.setTextDatum( textdatum_t::bottom_left     );
  lcd.setTextDatum( textdatum_t::bottom_center   );
  lcd.setTextDatum( textdatum_t::bottom_right    );
  // ※"textdatum_t::"可以省略
  // ※print系列函数只有垂直方向的指定有效，水平方向的指定无效。

  // 右下对齐
  lcd.setTextDatum( bottom_right );
  lcd.drawString("bottom_right",  lcd.width() / 2,  lcd.height() / 2);

  // 左下对齐
  lcd.setTextDatum( bottom_left );
  lcd.drawString("bottom_left",  lcd.width() / 2,  lcd.height() / 2);

  // 右上对齐
  lcd.setTextDatum( top_right );
  lcd.drawString("top_right",  lcd.width() / 2,  lcd.height() / 2);

  // 左上对齐
  lcd.setTextDatum( top_left );
  lcd.drawString("top_left",  lcd.width() / 2,  lcd.height() / 2);


  // 在基准坐标绘制中心线
  lcd.drawFastVLine(lcd.width() / 2, 0, lcd.height(), 0xFFFFFFU);
  lcd.drawFastHLine(0, lcd.height() / 2, lcd.width(), 0xFFFFFFU);


  delay(3000);
  drawGradation();

  lcd.setFont(&Font2);
  lcd.setCursor(0, 0);


  lcd.drawRect(8, 8, lcd.width() - 16, lcd.height() - 16, 0xFFFFFFU);

  // 使用setClipRect函数可以限制绘制范围。不会在指定范围外进行绘制。
  // ※不仅影响文本系列，还影响所有绘制函数。
  lcd.setClipRect(10, 10, lcd.width() - 20, lcd.height() - 20);


  // 使用setTextSize函数指定文字的放大率。
  // 第一个参数指定水平方向的倍率，第二个参数指定垂直方向的倍率。
  // 如果省略第二个参数，第一个参数的倍率将同时应用于垂直和水平方向。
  lcd.setTextSize(2.7, 4);
  lcd.println("Size 2.7 x 4");

  lcd.setTextSize(2.5);
  lcd.println("Size 2.5 x 2.5");

  lcd.setTextSize(1.5, 2);
  lcd.println("Size 1.5 x 2");

  delay(1000);

  lcd.setTextColor(0xFFFFFFU, 0);
  for (float i = 0; i < 30; i += 0.01) {
    lcd.setTextSize(sin(i)+1.1, cos(i)+1.1);
    lcd.drawString("size test", 10, 10);
  }

  lcd.setTextSize(1);

  // 使用setTextWrap函数指定print函数到达画面端（绘制范围端）时的换行动作。
  // 如果第一个参数为true，到达右端后将移动到左端。
  // 如果第二个参数为true，到达下端后将移动到上端。（省略时：false）
  lcd.setTextWrap(false);
  lcd.println("setTextWrap(false) testing... long long long long string wrap test string ");
  // false指定时不调整位置，超出绘制范围的部分不会被绘制。

  lcd.setTextWrap(true);
  lcd.setTextColor(0xFFFF00U, 0);
  lcd.println("setTextWrap(true) testing... long long long long string wrap test string ");
  // true指定时将自动调整位置以适应绘制范围内。

  delay(1000);

  // 第二个参数指定为true时，到达画面下端后将从上端继续绘制。
  lcd.setTextColor(0xFFFFFFU, 0);
  lcd.setTextWrap(true, true);
  lcd.println("setTextWrap(true, true) testing...");
  for (int i = 0; i < 100; ++i) {
    lcd.printf("wrap test %03d ", i);
    delay(50);
  }


  drawGradation();

  // 使用setTextScroll函数指定到达画面下端时的滚动动作。
  // 使用setScrollRect函数指定滚动的矩形范围。（未指定时整个画面滚动）
  // ※滚动功能需要LCD支持像素读取。
  lcd.setTextScroll(true);

  // 第1～第4参数指定X Y Width Height的矩形范围，第5参数指定滚动后的颜色。第5参数可省略（省略时不变）
  lcd.setScrollRect(10, 10, lcd.width() - 20, lcd.height() - 20, 0x00001FU);

  for (int i = 0; i < 50; ++i) {
    lcd.printf("scroll test %d \n", i);
  }


  // 解除setClipRect的范围指定。
  lcd.clearClipRect();

  // 解除setScrollRect的范围指定。
  lcd.clearScrollRect();


  lcd.setTextSize(1);
  lcd.setTextColor(0xFFFFFFU, 0);


  // 使用setTextPadding函数可以指定drawString系列函数在背景填充时的最小宽度。
  lcd.setTextPadding(100);


  drawGradation();
}

void drawNumberTest(const lgfx::IFont* font)
{
  lcd.setFont(font);

  lcd.fillScreen(0x0000FF);

  lcd.setColor(0xFFFF00U);
  lcd.drawFastVLine( 80, 0, 240);
  lcd.drawFastVLine(160, 0, 240);
  lcd.drawFastVLine(240, 0, 240);
  lcd.drawFastHLine(0,  45, 320);
  lcd.drawFastHLine(0,  95, 320);
  lcd.drawFastHLine(0, 145, 320);
  lcd.drawFastHLine(0, 195, 320);

  for (int i = 0; i < 200; ++i) {
    lcd.setTextDatum( textdatum_t::bottom_right    );     lcd.drawNumber(i,  80,  45);
    lcd.setTextDatum( textdatum_t::bottom_center   );     lcd.drawNumber(i, 160,  45);
    lcd.setTextDatum( textdatum_t::bottom_left     );     lcd.drawNumber(i, 240,  45);
    lcd.setTextDatum( textdatum_t::baseline_right  );     lcd.drawNumber(i,  80,  95);
    lcd.setTextDatum( textdatum_t::baseline_center );     lcd.drawNumber(i, 160,  95);
    lcd.setTextDatum( textdatum_t::baseline_left   );     lcd.drawNumber(i, 240,  95);
    lcd.setTextDatum( textdatum_t::middle_right    );     lcd.drawNumber(i,  80, 145);
    lcd.setTextDatum( textdatum_t::middle_center   );     lcd.drawNumber(i, 160, 145);
    lcd.setTextDatum( textdatum_t::middle_left     );     lcd.drawNumber(i, 240, 145);
    lcd.setTextDatum( textdatum_t::top_right       );     lcd.drawNumber(i,  80, 195);
    lcd.setTextDatum( textdatum_t::top_center      );     lcd.drawNumber(i, 160, 195);
    lcd.setTextDatum( textdatum_t::top_left        );     lcd.drawNumber(i, 240, 195);
  }
}

void loop(void)
{
// ※名称以"Free"开头的字体有9pt、12pt、18pt、24pt四种。
  drawNumberTest( &fonts::Font0                   );
  drawNumberTest( &fonts::Font2                   );
  drawNumberTest( &fonts::Font4                   );
  drawNumberTest( &fonts::Font6                   );
  drawNumberTest( &fonts::Font7                   );
  drawNumberTest( &fonts::Font8                   );
  drawNumberTest( &fonts::TomThumb                );
  drawNumberTest( &fonts::FreeMono9pt7b           );
  drawNumberTest( &fonts::FreeMonoBold9pt7b       );
  drawNumberTest( &fonts::FreeMonoOblique9pt7b    );
  drawNumberTest( &fonts::FreeMonoBoldOblique9pt7b);
  drawNumberTest( &fonts::FreeSans9pt7b           );
  drawNumberTest( &fonts::FreeSansBold9pt7b       );
  drawNumberTest( &fonts::FreeSansOblique9pt7b    );
  drawNumberTest( &fonts::FreeSansBoldOblique9pt7b);
  drawNumberTest( &fonts::FreeSerif9pt7b          );
  drawNumberTest( &fonts::FreeSerifBold9pt7b      );
  drawNumberTest( &fonts::FreeSerifItalic9pt7b    );
  drawNumberTest( &fonts::FreeSerifBoldItalic9pt7b);
  drawNumberTest( &fonts::Orbitron_Light_24       );
  drawNumberTest( &fonts::Roboto_Thin_24          );
  drawNumberTest( &fonts::Satisfy_24              );
  drawNumberTest( &fonts::Yellowtail_32           );
}