freetype-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Git][freetype/freetype-demos][gsoc-2022-chariri-2] 3 commits: * src/fti


From: Charlie Jiang (@cqjjjzr)
Subject: [Git][freetype/freetype-demos][gsoc-2022-chariri-2] 3 commits: * src/ftinspect/models/customcomboboxmodels.cpp: Disable subpixel light too.
Date: Tue, 26 Jul 2022 11:05:10 +0000

Charlie Jiang pushed to branch gsoc-2022-chariri-2 at FreeType / FreeType Demo Programs

Commits:

  • 1f97743b
    by Charlie Jiang at 2022-07-26T16:13:41+08:00
    * src/ftinspect/models/customcomboboxmodels.cpp: Disable subpixel light too.
    
    When "Light" AA mode is disabled, the SubPixel-Light mode should be disabled
    as well.
    
  • 7532d1a0
    by Charlie Jiang at 2022-07-26T19:00:43+08:00
    [ftinspect] Support color layer font.
    
    TODO: After implemented SFNT, allow showing of the palette names.
    
    * src/ftinspect/engine/engine.cpp, src/ftinspect/engine/engine.hpp:
      Add fields to hold palettes info and functions to retrieve palette.
      Add options about color layer rendering.
      Add `tryDirectRenderColorLayers` to perform color layer rendering.
    
    * src/ftinspect/engine/stringrenderer.cpp,
      src/ftinspect/engine/stringrenderer.hpp: Support color layered rendering.
    
    * src/ftinspect/rendering/glyphcontinuous.cpp,
      src/ftinspect/rendering/glyphcontinuous.hpp: Add a callback to draw
      pre-converted images.
    
    * src/ftinspect/engine/paletteinfo.cpp,
      src/ftinspect/engine/paletteinfo.hpp: New files. `PaletteInfo` holds
      metadata about palettes.
    
    * src/ftinspect/panels/continuous.cpp: Bugfix: Sync settings before calling
      renderer to reload all glyphs.
    
    * src/ftinspect/panels/settingpanel.cpp,
      src/ftinspect/panels/settingpanel.hpp:
      Add "Enable Color Layer" and "Palette" options. Add code populating
      palettes from the engine, so rename `checkHinting` to a more general
      `onFontChanged`. Minor lifecycle bugfix.
    
    * src/ftinspect/maingui.cpp: Rename `SettingPanel::checkHinting` to
      `onFontChanged`.
    
    * src/ftinspect/CMakeLists.txt, src/ftinspect/meson.build: Updated.
    
  • 6a264517
    by Charlie Jiang at 2022-07-26T19:03:03+08:00
    [ftinspect] Support color layer rendering in Singular View.
    
    * src/ftinspect/rendering/glyphbitmap.cpp,
      src/ftinspect/rendering/glyphbitmap.hpp:
      Add an extra argument `glyphIndex` in the constructor and attempt to
      render the glyph as color layered in the first.
    
    * src/ftinspect/panels/singular.cpp: Pass glyph index to `GlyphBitmap`.
    

18 changed files:

Changes:

  • src/ftinspect/CMakeLists.txt
    ... ... @@ -23,6 +23,7 @@ add_executable(ftinspect
    23 23
       "engine/engine.cpp"
    
    24 24
       "engine/fontfilemanager.cpp"
    
    25 25
       "engine/charmap.cpp"
    
    26
    +  "engine/paletteinfo.cpp"
    
    26 27
       "engine/stringrenderer.cpp"
    
    27 28
     
    
    28 29
       "rendering/glyphbitmap.cpp"
    

  • src/ftinspect/engine/engine.cpp
    ... ... @@ -343,6 +343,9 @@ Engine::loadFont(int fontIndex,
    343 343
         ftSize_ = NULL;
    
    344 344
         curFamilyName_ = QString();
    
    345 345
         curStyleName_ = QString();
    
    346
    +
    
    347
    +    curCharMaps_.clear();
    
    348
    +    curPaletteInfos_.clear();
    
    346 349
       }
    
    347 350
       else
    
    348 351
       {
    
    ... ... @@ -362,6 +365,8 @@ Engine::loadFont(int fontIndex,
    362 365
         curCharMaps_.reserve(face->num_charmaps);
    
    363 366
         for (int i = 0; i < face->num_charmaps; i++)
    
    364 367
           curCharMaps_.emplace_back(i, face->charmaps[i]);
    
    368
    +
    
    369
    +    loadPaletteInfos();
    
    365 370
       }
    
    366 371
     
    
    367 372
       curNumGlyphs_ = numGlyphs;
    
    ... ... @@ -380,6 +385,22 @@ Engine::reloadFont()
    380 385
     }
    
    381 386
     
    
    382 387
     
    
    388
    +void
    
    389
    +Engine::loadPalette()
    
    390
    +{
    
    391
    +  palette_ = NULL;
    
    392
    +  if (paletteData_.num_palettes == 0
    
    393
    +      || paletteIndex_ < 0
    
    394
    +      || paletteData_.num_palettes <= paletteIndex_)
    
    395
    +    return;
    
    396
    +
    
    397
    +  FT_Palette_Select(ftSize_->face, 
    
    398
    +                    static_cast<FT_UShort>(paletteIndex_),
    
    399
    +                    &palette_);
    
    400
    +  // XXX error handling
    
    401
    +}
    
    402
    +
    
    403
    +
    
    383 404
     void
    
    384 405
     Engine::removeFont(int fontIndex, bool closeFile)
    
    385 406
     {
    
    ... ... @@ -817,6 +838,24 @@ Engine::queryEngine()
    817 838
     }
    
    818 839
     
    
    819 840
     
    
    841
    +void
    
    842
    +Engine::loadPaletteInfos()
    
    843
    +{
    
    844
    +  curPaletteInfos_.clear();
    
    845
    +
    
    846
    +  if (FT_Palette_Data_Get(ftSize_->face, &paletteData_))
    
    847
    +  {
    
    848
    +    // XXX Error handling
    
    849
    +    paletteData_.num_palettes = 0;
    
    850
    +    return;
    
    851
    +  }
    
    852
    +
    
    853
    +  curPaletteInfos_.reserve(paletteData_.num_palettes);
    
    854
    +  for (int i = 0; i < paletteData_.num_palettes; ++i)
    
    855
    +    curPaletteInfos_.emplace_back(ftSize_->face, paletteData_, i);
    
    856
    +}
    
    857
    +
    
    858
    +
    
    820 859
     void
    
    821 860
     convertLCDToARGB(FT_Bitmap& bitmap,
    
    822 861
                      QImage& image,
    
    ... ... @@ -978,6 +1017,131 @@ Engine::computeGlyphOffset(FT_Glyph glyph, bool inverseY)
    978 1017
     }
    
    979 1018
     
    
    980 1019
     
    
    1020
    +QImage*
    
    1021
    +Engine::tryDirectRenderColorLayers(int glyphIndex,
    
    1022
    +                                   QRect* outRect)
    
    1023
    +{
    
    1024
    +  if (palette_ == NULL 
    
    1025
    +      || !useColorLayer_ 
    
    1026
    +      || paletteIndex_ >= paletteData_.num_palettes)
    
    1027
    +    return NULL;
    
    1028
    +
    
    1029
    +  FT_LayerIterator iter = {};
    
    1030
    +  
    
    1031
    +  FT_UInt layerGlyphIdx = 0;
    
    1032
    +  FT_UInt layerColorIdx = 0;
    
    1033
    +
    
    1034
    +  bool next = FT_Get_Color_Glyph_Layer(ftSize_->face,
    
    1035
    +                                       glyphIndex,
    
    1036
    +                                       &layerGlyphIdx,
    
    1037
    +                                       &layerColorIdx,
    
    1038
    +                                       &iter);
    
    1039
    +  if (!next)
    
    1040
    +    return NULL;
    
    1041
    +
    
    1042
    +  // temporarily change lf
    
    1043
    +  auto oldLoadFlags = imageType_.flags;
    
    1044
    +  auto loadFlags = oldLoadFlags;
    
    1045
    +  loadFlags &= ~FT_LOAD_COLOR;
    
    1046
    +  loadFlags |= FT_LOAD_RENDER;
    
    1047
    +
    
    1048
    +  loadFlags &= ~FT_LOAD_TARGET_(0xF);
    
    1049
    +  loadFlags |= FT_LOAD_TARGET_NORMAL;
    
    1050
    +  imageType_.flags = loadFlags;
    
    1051
    +
    
    1052
    +  FT_Bitmap bitmap = {};
    
    1053
    +  FT_Bitmap_Init(&bitmap);
    
    1054
    +
    
    1055
    +  FT_Vector bitmapOffset = {};
    
    1056
    +  bool failed = false;
    
    1057
    +
    
    1058
    +  do
    
    1059
    +  {
    
    1060
    +    FT_Vector slotOffset;
    
    1061
    +    FT_Glyph glyph;
    
    1062
    +    if (FTC_ImageCache_Lookup(imageCache_,
    
    1063
    +                              &imageType_,
    
    1064
    +                              layerGlyphIdx,
    
    1065
    +                              &glyph,
    
    1066
    +                              NULL))
    
    1067
    +    {
    
    1068
    +      // XXX Error handling
    
    1069
    +      failed = true;
    
    1070
    +      break;
    
    1071
    +    }
    
    1072
    +
    
    1073
    +    if (glyph->format != FT_GLYPH_FORMAT_BITMAP)
    
    1074
    +      continue;
    
    1075
    +
    
    1076
    +    auto bitmapGlyph = reinterpret_cast<FT_BitmapGlyph>(glyph);
    
    1077
    +    slotOffset.x = bitmapGlyph->left << 6;
    
    1078
    +    slotOffset.y = bitmapGlyph->top << 6;
    
    1079
    +
    
    1080
    +    FT_Color color = {};
    
    1081
    +
    
    1082
    +    if (layerColorIdx == 0xFFFF)
    
    1083
    +    {
    
    1084
    +      // TODO: FT_Palette_Get_Foreground_Color: #1134
    
    1085
    +      if (paletteData_.palette_flags
    
    1086
    +          && (paletteData_.palette_flags[paletteIndex_] 
    
    1087
    +              & FT_PALETTE_FOR_DARK_BACKGROUND))
    
    1088
    +      {
    
    1089
    +        /* white opaque */
    
    1090
    +        color.blue = 0xFF;
    
    1091
    +        color.green = 0xFF;
    
    1092
    +        color.red = 0xFF;
    
    1093
    +        color.alpha = 0xFF;
    
    1094
    +      }
    
    1095
    +      else
    
    1096
    +      {
    
    1097
    +        /* black opaque */
    
    1098
    +        color.blue = 0x00;
    
    1099
    +        color.green = 0x00;
    
    1100
    +        color.red = 0x00;
    
    1101
    +        color.alpha = 0xFF;
    
    1102
    +      }
    
    1103
    +    }
    
    1104
    +    else if (layerColorIdx < paletteData_.num_palette_entries)
    
    1105
    +      color = palette_[layerColorIdx];
    
    1106
    +    else
    
    1107
    +      continue;
    
    1108
    +
    
    1109
    +    if (FT_Bitmap_Blend(library_,
    
    1110
    +                        &bitmapGlyph->bitmap, slotOffset,
    
    1111
    +                        &bitmap, &bitmapOffset,
    
    1112
    +                        color))
    
    1113
    +    {
    
    1114
    +      // XXX error
    
    1115
    +      failed = true;
    
    1116
    +      break;
    
    1117
    +    }
    
    1118
    +  } while (FT_Get_Color_Glyph_Layer(ftSize_->face,
    
    1119
    +                                    glyphIndex,
    
    1120
    +                                    &layerGlyphIdx,
    
    1121
    +                                    &layerColorIdx,
    
    1122
    +                                    &iter));
    
    1123
    +
    
    1124
    +  imageType_.flags = oldLoadFlags;
    
    1125
    +  if (failed)
    
    1126
    +  {
    
    1127
    +    FT_Bitmap_Done(library_, &bitmap);
    
    1128
    +    return NULL;
    
    1129
    +  }
    
    1130
    +
    
    1131
    +  auto img = convertBitmapToQImage(&bitmap);
    
    1132
    +  if (outRect)
    
    1133
    +  {
    
    1134
    +    outRect->setSize(img->size());
    
    1135
    +    outRect->setLeft(bitmapOffset.x >> 6);
    
    1136
    +    outRect->setTop(bitmapOffset.y >> 6);
    
    1137
    +  }
    
    1138
    +
    
    1139
    +  FT_Bitmap_Done(library_, &bitmap);
    
    1140
    +
    
    1141
    +  return img;
    
    1142
    +}
    
    1143
    +
    
    1144
    +
    
    981 1145
     QHash<FT_Glyph_Format, QString> glyphFormatNamesCache;
    
    982 1146
     QHash<FT_Glyph_Format, QString>&
    
    983 1147
     glyphFormatNames()
    

  • src/ftinspect/engine/engine.hpp
    ... ... @@ -7,6 +7,7 @@
    7 7
     
    
    8 8
     #include "fontfilemanager.hpp"
    
    9 9
     #include "charmap.hpp"
    
    10
    +#include "paletteinfo.hpp"
    
    10 11
     
    
    11 12
     #include <vector>
    
    12 13
     #include <QString>
    
    ... ... @@ -19,6 +20,7 @@
    19 20
     #include <freetype/ftoutln.h>
    
    20 21
     #include <freetype/ftcache.h>
    
    21 22
     #include <freetype/ftlcdfil.h>
    
    23
    +#include <freetype/ftcolor.h>
    
    22 24
     
    
    23 25
     
    
    24 26
     // This structure maps the (font, face, instance) index triplet to abstract
    
    ... ... @@ -94,9 +96,22 @@ public:
    94 96
                                    bool inverseRectY);
    
    95 97
       QPoint computeGlyphOffset(FT_Glyph glyph, bool inverseY);
    
    96 98
     
    
    99
    +  /*
    
    100
    +   * Directly render the glyph at the specified index
    
    101
    +   * to a `QImage`. If you want to perform color-layer
    
    102
    +   * rendering, call this before trying to load the
    
    103
    +   * glyph and do normal rendering, If the returning
    
    104
    +   * value is non-NULL, then there's no need to
    
    105
    +   * load the glyph the normal way, just draw the `QImage`.
    
    106
    +   * Will return NULL if not enabled or color layers not available.
    
    107
    +   */
    
    108
    +  QImage* tryDirectRenderColorLayers(int glyphIndex,
    
    109
    +                                     QRect* outRect);
    
    110
    +
    
    97 111
       // reload current triplet, but with updated settings, useful for updating
    
    98 112
       // `ftSize_` only
    
    99
    -  void reloadFont(); 
    
    113
    +  void reloadFont();
    
    114
    +  void loadPalette();
    
    100 115
     
    
    101 116
       void openFonts(QStringList fontFileNames);
    
    102 117
       void removeFont(int fontIndex, bool closeFile = true);
    
    ... ... @@ -132,6 +147,7 @@ public:
    132 147
       FT_Vector currentFontKerning(int glyphIndex, int prevIndex);
    
    133 148
       
    
    134 149
       std::vector<CharMapInfo>& currentFontCharMaps() { return curCharMaps_; }
    
    150
    +  std::vector<PaletteInfo>& currentFontPalettes() { return curPaletteInfos_; }
    
    135 151
       FontFileManager& fontFileManager() { return fontFileManager_; }
    
    136 152
       EngineDefaultValues& engineDefaults() { return engineDefaults_; }
    
    137 153
       bool antiAliasingEnabled() { return antiAliasingEnabled_; }
    
    ... ... @@ -164,6 +180,8 @@ public:
    164 180
       void setRenderMode(int mode) { renderMode_ = mode; }
    
    165 181
       void setAntiAliasingEnabled(bool enabled) { antiAliasingEnabled_ = enabled; }
    
    166 182
       void setEmbeddedBitmap(bool force) { embeddedBitmap_ = force; }
    
    183
    +  void setUseColorLayer(bool colorLayer) { useColorLayer_ = colorLayer; }
    
    184
    +  void setPaletteIndex(int index) { paletteIndex_ = index; }
    
    167 185
       void setLCDUsesBGR(bool isBGR) { lcdUsesBGR_ = isBGR; }
    
    168 186
       void setLCDSubPixelPositioning(bool sp) { lcdSubPixelPositioning_ = sp; }
    
    169 187
     
    
    ... ... @@ -191,6 +209,7 @@ private:
    191 209
       QString curStyleName_;
    
    192 210
       int curNumGlyphs_ = -1;
    
    193 211
       std::vector<CharMapInfo> curCharMaps_;
    
    212
    +  std::vector<PaletteInfo> curPaletteInfos_;
    
    194 213
     
    
    195 214
       FT_Library library_;
    
    196 215
       FTC_Manager cacheManager_;
    
    ... ... @@ -199,8 +218,10 @@ private:
    199 218
       FTC_CMapCache cmapCache_;
    
    200 219
     
    
    201 220
       FTC_ScalerRec scaler_ = {};
    
    202
    -  FT_Size ftSize_;
    
    203 221
       FTC_ImageTypeRec imageType_;
    
    222
    +  FT_Size ftSize_;
    
    223
    +  FT_Palette_Data paletteData_ = {};
    
    224
    +  FT_Color* palette_ = NULL;
    
    204 225
     
    
    205 226
       EngineDefaultValues engineDefaults_;
    
    206 227
     
    
    ... ... @@ -219,6 +240,8 @@ private:
    219 240
       bool doBlueZoneHinting_;
    
    220 241
       bool showSegments_;
    
    221 242
       bool embeddedBitmap_;
    
    243
    +  bool useColorLayer_;
    
    244
    +  int paletteIndex_ = -1;
    
    222 245
       int antiAliasingTarget_;
    
    223 246
       bool lcdUsesBGR_;
    
    224 247
       bool lcdSubPixelPositioning_;
    
    ... ... @@ -228,6 +251,7 @@ private:
    228 251
       unsigned long loadFlags_;
    
    229 252
     
    
    230 253
       void queryEngine();
    
    254
    +  void loadPaletteInfos();
    
    231 255
     
    
    232 256
     public:
    
    233 257
     
    

  • src/ftinspect/engine/paletteinfo.cpp
    1
    +// paletteinfo.cpp
    
    2
    +
    
    3
    +// Copyright (C) 2022 by Charlie Jiang.
    
    4
    +
    
    5
    +#include "paletteinfo.hpp"
    
    6
    +
    
    7
    +PaletteInfo::PaletteInfo(FT_Face face, 
    
    8
    +                         FT_Palette_Data& data, 
    
    9
    +                         int index)
    
    10
    +: index(index)
    
    11
    +{
    
    12
    +  if (data.palette_name_ids)
    
    13
    +  {
    
    14
    +    auto id = data.palette_name_ids[index];
    
    15
    +    FT_SfntName sname;
    
    16
    +    FT_Get_Sfnt_Name(face, id, &sname);
    
    17
    +    name = "(SFNT no impl)";
    
    18
    +    // TODO: Get SFNT Name: After implemented SFNT names functionality.
    
    19
    +  }
    
    20
    +  else
    
    21
    +  {
    
    22
    +    name = "(unnamed)";
    
    23
    +  }
    
    24
    +}
    
    25
    +
    
    26
    +
    
    27
    +// end of paletteinfo.cpp

  • src/ftinspect/engine/paletteinfo.hpp
    1
    +// paletteinfo.hpp
    
    2
    +
    
    3
    +// Copyright (C) 2022 by Charlie Jiang.
    
    4
    +
    
    5
    +#pragma once
    
    6
    +
    
    7
    +#include <QString>
    
    8
    +
    
    9
    +#include <freetype/freetype.h>
    
    10
    +#include <freetype/ftcolor.h>
    
    11
    +#include <freetype/ftsnames.h>
    
    12
    +
    
    13
    +struct PaletteInfo
    
    14
    +{
    
    15
    +  int index;
    
    16
    +  QString name;
    
    17
    +
    
    18
    +  PaletteInfo(FT_Face face, FT_Palette_Data& data, int index);
    
    19
    +};
    
    20
    +
    
    21
    +
    
    22
    +// end of paletteinfo.hpp

  • src/ftinspect/engine/stringrenderer.cpp
    ... ... @@ -150,6 +150,7 @@ void
    150 150
     StringRenderer::prepareRendering()
    
    151 151
     {
    
    152 152
       engine_->reloadFont();
    
    153
    +  engine_->loadPalette();
    
    153 154
       if (kerningDegree_ != KD_None)
    
    154 155
         trackingKerning_ = engine_->currentFontTrackingKerning(kerningDegree_);
    
    155 156
       else
    
    ... ... @@ -499,70 +500,83 @@ StringRenderer::renderLine(int x,
    499 500
         if (!ctx.glyph)
    
    500 501
           continue;
    
    501 502
     
    
    502
    -    // copy the glyph because we're doing manipulation
    
    503
    -    auto error = FT_Glyph_Copy(ctx.glyph, &image);
    
    504
    -    if (error)
    
    505
    -      continue;
    
    503
    +    advance = vertical_ ? ctx.vadvance : ctx.hadvance;
    
    506 504
     
    
    507
    -    glyphPreprocessCallback_(&image);
    
    505
    +    QRect rect;
    
    506
    +    QImage* colorLayerImage
    
    507
    +        = engine_->tryDirectRenderColorLayers(ctx.glyphIndex, &rect);
    
    508 508
     
    
    509
    -    if (image->format != FT_GLYPH_FORMAT_BITMAP)
    
    509
    +    if (colorLayerImage)
    
    510 510
         {
    
    511
    -      if (vertical_)
    
    512
    -        error = FT_Glyph_Transform(image, NULL, &ctx.vvector);
    
    513
    -
    
    514
    -      if (!error)
    
    515
    -      {
    
    516
    -        if (matrixEnabled_)
    
    517
    -          error = FT_Glyph_Transform(image, &matrix_, &pen);
    
    518
    -        else
    
    519
    -          error = FT_Glyph_Transform(image, NULL, &pen);
    
    520
    -      }
    
    521
    -
    
    522
    -      if (error)
    
    523
    -      {
    
    524
    -        FT_Done_Glyph(image);
    
    525
    -        continue;
    
    526
    -      }
    
    511
    +      rect.setX(rect.x() + (pen.x >> 6));
    
    512
    +      rect.setY(height - rect.y() - (pen.y >> 6));
    
    513
    +      renderImageCallback_(colorLayerImage, rect);
    
    527 514
         }
    
    528 515
         else
    
    529 516
         {
    
    530
    -      auto bitmap = reinterpret_cast<FT_BitmapGlyph>(image);
    
    517
    +      // copy the glyph because we're doing manipulation
    
    518
    +      auto error = FT_Glyph_Copy(ctx.glyph, &image);
    
    519
    +      if (error)
    
    520
    +        continue;
    
    521
    +
    
    522
    +      glyphPreprocessCallback_(&image);
    
    531 523
     
    
    532
    -      if (vertical_)
    
    524
    +      if (image->format != FT_GLYPH_FORMAT_BITMAP)
    
    533 525
           {
    
    534
    -        bitmap->left += (ctx.vvector.x + pen.x) >> 6;
    
    535
    -        bitmap->top += (ctx.vvector.y + pen.y) >> 6;
    
    526
    +        if (vertical_)
    
    527
    +          error = FT_Glyph_Transform(image, NULL, &ctx.vvector);
    
    528
    +
    
    529
    +        if (!error)
    
    530
    +        {
    
    531
    +          if (matrixEnabled_)
    
    532
    +            error = FT_Glyph_Transform(image, &matrix_, &pen);
    
    533
    +          else
    
    534
    +            error = FT_Glyph_Transform(image, NULL, &pen);
    
    535
    +        }
    
    536
    +
    
    537
    +        if (error)
    
    538
    +        {
    
    539
    +          FT_Done_Glyph(image);
    
    540
    +          continue;
    
    541
    +        }
    
    536 542
           }
    
    537 543
           else
    
    538 544
           {
    
    539
    -        bitmap->left += pen.x >> 6;
    
    540
    -        bitmap->top += pen.y >> 6;
    
    545
    +        auto bitmap = reinterpret_cast<FT_BitmapGlyph>(image);
    
    546
    +
    
    547
    +        if (vertical_)
    
    548
    +        {
    
    549
    +          bitmap->left += (ctx.vvector.x + pen.x) >> 6;
    
    550
    +          bitmap->top += (ctx.vvector.y + pen.y) >> 6;
    
    551
    +        }
    
    552
    +        else
    
    553
    +        {
    
    554
    +          bitmap->left += pen.x >> 6;
    
    555
    +          bitmap->top += pen.y >> 6;
    
    556
    +        }
    
    541 557
           }
    
    542
    -    }
    
    543 558
     
    
    544
    -    advance = vertical_ ? ctx.vadvance : ctx.hadvance;
    
    559
    +      if (matrixEnabled_)
    
    560
    +        FT_Vector_Transform(&advance, &matrix_);
    
    545 561
     
    
    546
    -    if (matrixEnabled_)
    
    547
    -      FT_Vector_Transform(&advance, &matrix_);
    
    562
    +      FT_Glyph_Get_CBox(image, FT_GLYPH_BBOX_PIXELS, &bbox);
    
    548 563
     
    
    549
    -    FT_Glyph_Get_CBox(image, FT_GLYPH_BBOX_PIXELS, &bbox);
    
    564
    +      // check bounding box; if it is completely outside the
    
    565
    +      // display surface, we don't need to render it
    
    566
    +      if (bbox.xMax >= 0 
    
    567
    +          && bbox.yMax >= 0
    
    568
    +          && bbox.xMin <= width
    
    569
    +          && bbox.yMin <= height)
    
    570
    +      {
    
    571
    +        FT_Vector penPos = { (pen.x >> 6), height - (pen.y >> 6) };
    
    572
    +        renderCallback_(image, penPos);
    
    573
    +      }
    
    550 574
     
    
    551
    -    // check bounding box; if it is completely outside the
    
    552
    -    // display surface, we don't need to render it
    
    553
    -    if (bbox.xMax >= 0 
    
    554
    -        && bbox.yMax >= 0
    
    555
    -        && bbox.xMin <= width
    
    556
    -        && bbox.yMin <= height)
    
    557
    -    {
    
    558
    -      FT_Vector penPos = { (pen.x >> 6), height - (pen.y >> 6) };
    
    559
    -      renderCallback_(image, penPos);
    
    575
    +      FT_Done_Glyph(image);
    
    560 576
         }
    
    561
    -
    
    577
    +    
    
    562 578
         pen.x += advance.x;
    
    563 579
         pen.y += advance.y;
    
    564
    -
    
    565
    -    FT_Done_Glyph(image);
    
    566 580
       }
    
    567 581
     
    
    568 582
       return offset + totalCount;
    

  • src/ftinspect/engine/stringrenderer.hpp
    ... ... @@ -62,6 +62,12 @@ public:
    62 62
        * position.
    
    63 63
        */
    
    64 64
       using RenderCallback = std::function<void(FT_Glyph, FT_Vector)>;
    
    65
    +  /*
    
    66
    +   * For color layered fonts, this will direct render the QImage for you.
    
    67
    +   * TODO: Remove `RenderCallback` and do QImage creation in this class?
    
    68
    +   * The receiver is responsible for deleteing the QImage.
    
    69
    +   */
    
    70
    +  using RenderImageCallback = std::function<void(QImage*, QRect)>;
    
    65 71
       /*
    
    66 72
        * The glyph pointer may be replaced. In that case, ownership is transfered
    
    67 73
        * to the renderer, and the new glyph will be eventually freed by
    
    ... ... @@ -90,6 +96,11 @@ public:
    90 96
         renderCallback_ = std::move(cb);
    
    91 97
       }
    
    92 98
       void
    
    99
    +  setImageCallback(RenderImageCallback cb)
    
    100
    +  {
    
    101
    +    renderImageCallback_ = std::move(cb);
    
    102
    +  }
    
    103
    +  void
    
    93 104
       setPreprocessCallback(PreprocessCallback cb)
    
    94 105
       {
    
    95 106
         glyphPreprocessCallback_ = std::move(cb);
    
    ... ... @@ -173,6 +184,7 @@ private:
    173 184
       bool matrixEnabled_ = false;
    
    174 185
     
    
    175 186
       RenderCallback renderCallback_;
    
    187
    +  RenderImageCallback renderImageCallback_;
    
    176 188
       PreprocessCallback glyphPreprocessCallback_;
    
    177 189
       LineBeginCallback lineBeginCallback_;
    
    178 190
     
    

  • src/ftinspect/maingui.cpp
    ... ... @@ -148,7 +148,7 @@ void
    148 148
     MainGUI::onTripletChanged()
    
    149 149
     {
    
    150 150
       auto state = settingPanel_->blockSignals(true);
    
    151
    -  settingPanel_->checkHinting();
    
    151
    +  settingPanel_->onFontChanged();
    
    152 152
       settingPanel_->blockSignals(state);
    
    153 153
       reloadCurrentTabFont();
    
    154 154
     }
    

  • src/ftinspect/meson.build
    ... ... @@ -23,6 +23,7 @@ if qt5_dep.found()
    23 23
         'engine/engine.cpp',
    
    24 24
         'engine/fontfilemanager.cpp',
    
    25 25
         'engine/charmap.cpp',
    
    26
    +    'engine/paletteinfo.cpp',
    
    26 27
         'engine/stringrenderer.cpp',
    
    27 28
     
    
    28 29
         'rendering/glyphbitmap.cpp',
    

  • src/ftinspect/models/customcomboboxmodels.cpp
    ... ... @@ -270,8 +270,10 @@ QVariant
    270 270
     AntiAliasingComboBoxModel::data(const QModelIndex& index,
    
    271 271
                                     int role) const
    
    272 272
     {
    
    273
    +  auto row = index.row();
    
    273 274
       if (role == Qt::ForegroundRole)
    
    274
    -    if (index.row() == AntiAliasing_Light && !lightAntiAliasingEnabled_)
    
    275
    +    if ((row == AntiAliasing_Light || row == AntiAliasing_Light_SubPixel)
    
    276
    +        && !lightAntiAliasingEnabled_)
    
    275 277
           return QApplication::palette().color(QPalette::Disabled, 
    
    276 278
                                                QPalette::Text);
    
    277 279
       return SimpleComboBoxModelImpl::data(index, role);
    
    ... ... @@ -281,7 +283,9 @@ AntiAliasingComboBoxModel::data(const QModelIndex& index,
    281 283
     Qt::ItemFlags
    
    282 284
     AntiAliasingComboBoxModel::flags(const QModelIndex& index) const
    
    283 285
     {
    
    284
    -  if (index.row() == AntiAliasing_Light && !lightAntiAliasingEnabled_)
    
    286
    +  auto row = index.row();
    
    287
    +  if ((row == AntiAliasing_Light || row == AntiAliasing_Light_SubPixel)
    
    288
    +      && !lightAntiAliasingEnabled_)
    
    285 289
         return Qt::ItemFlags {};
    
    286 290
       return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
    
    287 291
     }
    

  • src/ftinspect/panels/continuous.cpp
    ... ... @@ -230,6 +230,7 @@ ContinuousTab::charMapChanged()
    230 230
       }
    
    231 231
       updateLimitIndex();
    
    232 232
     
    
    233
    +  syncSettings();
    
    233 234
       canvas_->stringRenderer().reloadAll();
    
    234 235
       repaintGlyph();
    
    235 236
       lastCharMapIndex_ = newIndex;
    

  • src/ftinspect/panels/settingpanel.cpp
    ... ... @@ -25,14 +25,14 @@ SettingPanel::antiAliasingModeIndex()
    25 25
     void
    
    26 26
     SettingPanel::checkAllSettings()
    
    27 27
     {
    
    28
    -  checkHinting();
    
    28
    +  onFontChanged();
    
    29 29
       checkAutoHinting();
    
    30 30
       checkAntiAliasing();
    
    31 31
     }
    
    32 32
     
    
    33 33
     
    
    34 34
     void
    
    35
    -SettingPanel::checkHinting()
    
    35
    +SettingPanel::onFontChanged()
    
    36 36
     {
    
    37 37
       if (hintingCheckBox_->isChecked())
    
    38 38
       {
    
    ... ... @@ -76,6 +76,48 @@ SettingPanel::checkHinting()
    76 76
     
    
    77 77
         emit repaintNeeded();
    
    78 78
       }
    
    79
    +
    
    80
    +  populatePalettes();
    
    81
    +}
    
    82
    +
    
    83
    +
    
    84
    +void
    
    85
    +SettingPanel::populatePalettes()
    
    86
    +{
    
    87
    +  auto needToReload = false;
    
    88
    +  auto& newPalettes = engine_->currentFontPalettes();
    
    89
    +  if (newPalettes.size() != paletteComboBox_->count())
    
    90
    +    needToReload = true;
    
    91
    +  else
    
    92
    +    for (int i = 0; i < newPalettes.size(); ++i)
    
    93
    +    {
    
    94
    +      auto oldNameVariant = paletteComboBox_->itemData(i);
    
    95
    +      if (!oldNameVariant.canConvert<QString>())
    
    96
    +      {
    
    97
    +        needToReload = true;
    
    98
    +        break;
    
    99
    +      }
    
    100
    +      if (oldNameVariant.toString() != newPalettes[i].name)
    
    101
    +      {
    
    102
    +        needToReload = true;
    
    103
    +        break;
    
    104
    +      }
    
    105
    +    }
    
    106
    +  if (!needToReload)
    
    107
    +    return;
    
    108
    +
    
    109
    +  {
    
    110
    +    QSignalBlocker blocker(paletteComboBox_);
    
    111
    +    paletteComboBox_->clear();
    
    112
    +    for (int i = 0; i < newPalettes.size(); ++i)
    
    113
    +      paletteComboBox_->addItem(
    
    114
    +        QString("%1: %2")
    
    115
    +          .arg(i)
    
    116
    +          .arg(newPalettes[i].name),
    
    117
    +        newPalettes[i].name);
    
    118
    +  }
    
    119
    +
    
    120
    +  emit fontReloadNeeded();
    
    79 121
     }
    
    80 122
     
    
    81 123
     
    
    ... ... @@ -166,6 +208,14 @@ SettingPanel::checkAntiAliasing()
    166 208
     }
    
    167 209
     
    
    168 210
     
    
    211
    +void
    
    212
    +SettingPanel::checkPalette()
    
    213
    +{
    
    214
    +  paletteComboBox_->setEnabled(colorLayerCheckBox_->isChecked());
    
    215
    +  emit repaintNeeded();
    
    216
    +}
    
    217
    +
    
    218
    +
    
    169 219
     void
    
    170 220
     SettingPanel::syncSettings()
    
    171 221
     {
    
    ... ... @@ -190,6 +240,9 @@ SettingPanel::syncSettings()
    190 240
       engine_->setGamma(gammaSlider_->value());
    
    191 241
     
    
    192 242
       engine_->setEmbeddedBitmap(embeddedBitmapCheckBox_->isChecked());
    
    243
    +  engine_->setPaletteIndex(paletteComboBox_->currentIndex());
    
    244
    +
    
    245
    +  engine_->setUseColorLayer(colorLayerCheckBox_->isChecked());
    
    193 246
       engine_->setLCDUsesBGR(aaSettings.isBGR);
    
    194 247
       engine_->setLCDSubPixelPositioning(
    
    195 248
         antiAliasingComboBox_->currentIndex()
    
    ... ... @@ -210,12 +263,15 @@ SettingPanel::createConnections()
    210 263
       connect(lcdFilterComboBox_, 
    
    211 264
               QOverload<int>::of(&QComboBox::currentIndexChanged),
    
    212 265
               this, &SettingPanel::repaintNeeded);
    
    266
    +  connect(paletteComboBox_,
    
    267
    +          QOverload<int>::of(&QComboBox::currentIndexChanged), this,
    
    268
    +          &SettingPanel::repaintNeeded);
    
    213 269
     
    
    214 270
       connect(gammaSlider_, &QSlider::valueChanged,
    
    215 271
               this, &SettingPanel::repaintNeeded);
    
    216 272
       
    
    217 273
       connect(hintingCheckBox_, &QCheckBox::clicked,
    
    218
    -          this, &SettingPanel::checkHinting);
    
    274
    +          this, &SettingPanel::onFontChanged);
    
    219 275
     
    
    220 276
       connect(horizontalHintingCheckBox_, &QCheckBox::clicked,
    
    221 277
               this, &SettingPanel::repaintNeeded);
    
    ... ... @@ -230,6 +286,8 @@ SettingPanel::createConnections()
    230 286
               this, &SettingPanel::checkAutoHinting);
    
    231 287
       connect(embeddedBitmapCheckBox_, &QCheckBox::clicked,
    
    232 288
               this, &SettingPanel::fontReloadNeeded);
    
    289
    +  connect(colorLayerCheckBox_, &QCheckBox::clicked,
    
    290
    +          this, &SettingPanel::checkPalette);
    
    233 291
     }
    
    234 292
     
    
    235 293
     
    
    ... ... @@ -252,6 +310,7 @@ SettingPanel::createLayout()
    252 310
       blueZoneHintingCheckBox_ = new QCheckBox(tr("Blue-Zone Hinting"), this);
    
    253 311
       segmentDrawingCheckBox_ = new QCheckBox(tr("Segment Drawing"), this);
    
    254 312
       embeddedBitmapCheckBox_ = new QCheckBox(tr("Enable Embedded Bitmap"), this);
    
    313
    +  colorLayerCheckBox_ = new QCheckBox(tr("Enable Color Layer"), this);
    
    255 314
     
    
    256 315
       antiAliasingLabel_ = new QLabel(tr("Anti-Aliasing"), this);
    
    257 316
       antiAliasingLabel_->setAlignment(Qt::AlignRight);
    
    ... ... @@ -261,7 +320,7 @@ SettingPanel::createLayout()
    261 320
       antiAliasingComboBox_->setModel(antiAliasingComboBoxModel_);
    
    262 321
       antiAliasingLabel_->setBuddy(antiAliasingComboBox_);
    
    263 322
     
    
    264
    -  lcdFilterLabel_ = new QLabel(tr("LCD Filter"));
    
    323
    +  lcdFilterLabel_ = new QLabel(tr("LCD Filter"), this);
    
    265 324
       lcdFilterLabel_->setAlignment(Qt::AlignRight);
    
    266 325
     
    
    267 326
       lcdFilterComboboxModel_ = new LCDFilterComboBoxModel(this);
    
    ... ... @@ -269,6 +328,11 @@ SettingPanel::createLayout()
    269 328
       lcdFilterComboBox_->setModel(lcdFilterComboboxModel_);
    
    270 329
       lcdFilterLabel_->setBuddy(lcdFilterComboBox_);
    
    271 330
     
    
    331
    +  paletteLabel_ = new QLabel(tr("Palette: "), this);
    
    332
    +
    
    333
    +  paletteComboBox_ = new QComboBox(this);
    
    334
    +  paletteLabel_->setBuddy(paletteComboBox_);
    
    335
    +
    
    272 336
       int width;
    
    273 337
       // make all labels have the same width
    
    274 338
       width = hintingModeLabel_->minimumSizeHint().width();
    
    ... ... @@ -327,6 +391,10 @@ SettingPanel::createLayout()
    327 391
       gammaLayout_->addWidget(gammaLabel_);
    
    328 392
       gammaLayout_->addWidget(gammaSlider_);
    
    329 393
     
    
    394
    +  paletteLayout_ = new QHBoxLayout;
    
    395
    +  paletteLayout_->addWidget(paletteLabel_);
    
    396
    +  paletteLayout_->addWidget(paletteComboBox_);
    
    397
    +
    
    330 398
       generalTabLayout_ = new QVBoxLayout;
    
    331 399
       generalTabLayout_->addWidget(hintingCheckBox_);
    
    332 400
       generalTabLayout_->addLayout(hintingModeLayout_);
    
    ... ... @@ -343,6 +411,8 @@ SettingPanel::createLayout()
    343 411
       generalTabLayout_->addStretch(1);
    
    344 412
       generalTabLayout_->addLayout(gammaLayout_);
    
    345 413
       generalTabLayout_->addWidget(embeddedBitmapCheckBox_);
    
    414
    +  generalTabLayout_->addWidget(colorLayerCheckBox_);
    
    415
    +  generalTabLayout_->addLayout(paletteLayout_);
    
    346 416
       generalTabLayout_->addSpacing(20); // XXX px
    
    347 417
       generalTabLayout_->addStretch(1);
    
    348 418
     
    
    ... ... @@ -393,6 +463,7 @@ SettingPanel::setDefaults()
    393 463
       verticalHintingCheckBox_->setChecked(true);
    
    394 464
       blueZoneHintingCheckBox_->setChecked(true);
    
    395 465
       embeddedBitmapCheckBox_->setChecked(false);
    
    466
    +  colorLayerCheckBox_->setChecked(true);
    
    396 467
     
    
    397 468
       gammaSlider_->setValue(18); // 1.8
    
    398 469
     }
    

  • src/ftinspect/panels/settingpanel.hpp
    ... ... @@ -36,10 +36,11 @@ signals:
    36 36
     
    
    37 37
     public slots:
    
    38 38
       void checkAllSettings();
    
    39
    -  void checkHinting();
    
    39
    +  void onFontChanged();
    
    40 40
       void checkHintingMode();
    
    41 41
       void checkAutoHinting();
    
    42 42
       void checkAntiAliasing();
    
    43
    +  void checkPalette();
    
    43 44
     
    
    44 45
     private:
    
    45 46
       Engine* engine_;
    
    ... ... @@ -56,6 +57,7 @@ private:
    56 57
       QLabel* antiAliasingLabel_;
    
    57 58
       QLabel* hintingModeLabel_;
    
    58 59
       QLabel* lcdFilterLabel_;
    
    60
    +  QLabel* paletteLabel_;
    
    59 61
     
    
    60 62
       QCheckBox* hintingCheckBox_;
    
    61 63
       QCheckBox* horizontalHintingCheckBox_;
    
    ... ... @@ -64,6 +66,7 @@ private:
    64 66
       QCheckBox* segmentDrawingCheckBox_;
    
    65 67
       QCheckBox* autoHintingCheckBox_;
    
    66 68
       QCheckBox* embeddedBitmapCheckBox_;
    
    69
    +  QCheckBox* colorLayerCheckBox_;
    
    67 70
     
    
    68 71
       AntiAliasingComboBoxModel* antiAliasingComboBoxModel_;
    
    69 72
       HintingModeComboBoxModel* hintingModeComboBoxModel_;
    
    ... ... @@ -72,6 +75,7 @@ private:
    72 75
       QComboBox* hintingModeComboBox_;
    
    73 76
       QComboBox* antiAliasingComboBox_;
    
    74 77
       QComboBox* lcdFilterComboBox_;
    
    78
    +  QComboBox* paletteComboBox_;
    
    75 79
     
    
    76 80
       QSlider* gammaSlider_;
    
    77 81
     
    
    ... ... @@ -84,6 +88,7 @@ private:
    84 88
       QHBoxLayout* antiAliasingLayout_;
    
    85 89
       QHBoxLayout* lcdFilterLayout_;
    
    86 90
       QHBoxLayout* gammaLayout_;
    
    91
    +  QHBoxLayout* paletteLayout_;
    
    87 92
     
    
    88 93
       QVBoxLayout* generalTabLayout_;
    
    89 94
     
    
    ... ... @@ -92,6 +97,8 @@ private:
    92 97
       void createConnections();
    
    93 98
       void createLayout();
    
    94 99
       void setDefaults();
    
    100
    +
    
    101
    +  void populatePalettes();
    
    95 102
     };
    
    96 103
     
    
    97 104
     
    

  • src/ftinspect/panels/singular.cpp
    ... ... @@ -94,7 +94,8 @@ SingularTab::drawGlyph()
    94 94
         if (showBitmapCheckBox_->isChecked())
    
    95 95
         {
    
    96 96
           currentGlyphBitmapItem_
    
    97
    -        = new GlyphBitmap(glyph,
    
    97
    +        = new GlyphBitmap(currentGlyphIndex_, 
    
    98
    +                          glyph,
    
    98 99
                               engine_);
    
    99 100
           glyphScene_->addItem(currentGlyphBitmapItem_);
    
    100 101
         }
    

  • src/ftinspect/rendering/glyphbitmap.cpp
    ... ... @@ -14,12 +14,21 @@
    14 14
     #include <freetype/ftbitmap.h>
    
    15 15
     
    
    16 16
     
    
    17
    -GlyphBitmap::GlyphBitmap(FT_Glyph glyph,
    
    17
    +GlyphBitmap::GlyphBitmap(int glyphIndex, 
    
    18
    +                         FT_Glyph glyph,
    
    18 19
                              Engine* engine)
    
    19 20
     {
    
    20 21
       QRect bRect;
    
    22
    +  image_ = engine->tryDirectRenderColorLayers(glyphIndex, &bRect);
    
    23
    +  if (image_)
    
    24
    +  {
    
    25
    +    bRect.setTop(-bRect.top());
    
    26
    +    boundingRect_ = bRect; // QRect to QRectF
    
    27
    +    return;
    
    28
    +  }
    
    29
    +
    
    21 30
       image_ = engine->convertGlyphToQImage(glyph, &bRect, true);
    
    22
    -  boundingRect_ = bRect; // QRectF to QRect
    
    31
    +  boundingRect_ = bRect; // QRect to QRectF
    
    23 32
     }
    
    24 33
     
    
    25 34
     
    

  • src/ftinspect/rendering/glyphbitmap.hpp
    ... ... @@ -20,7 +20,8 @@ class GlyphBitmap
    20 20
     : public QGraphicsItem
    
    21 21
     {
    
    22 22
     public:
    
    23
    -  GlyphBitmap(FT_Glyph glyph,
    
    23
    +  GlyphBitmap(int glyphIndex,
    
    24
    +              FT_Glyph glyph,
    
    24 25
                   Engine* engine);
    
    25 26
       ~GlyphBitmap() override;
    
    26 27
       QRectF boundingRect() const override;
    

  • src/ftinspect/rendering/glyphcontinuous.cpp
    ... ... @@ -101,6 +101,11 @@ GlyphContinuous::paintByRenderer(QPainter* painter)
    101 101
         {
    
    102 102
           drawSingleGlyph(painter, glyph, penPos);
    
    103 103
         });
    
    104
    +  stringRenderer_.setImageCallback(
    
    105
    +    [&](QImage* image, QRect pos)
    
    106
    +    {
    
    107
    +      drawSingleGlyphImage(painter, image, pos);
    
    108
    +    });
    
    104 109
       stringRenderer_.setPreprocessCallback(
    
    105 110
         [&](FT_Glyph* ptr)
    
    106 111
         {
    
    ... ... @@ -285,4 +290,17 @@ GlyphContinuous::drawSingleGlyph(QPainter* painter,
    285 290
     }
    
    286 291
     
    
    287 292
     
    
    293
    +void
    
    294
    +GlyphContinuous::drawSingleGlyphImage(QPainter* painter,
    
    295
    +                                      QImage* image,
    
    296
    +                                      QRect pos)
    
    297
    +{
    
    298
    +  // TODO red square?
    
    299
    +
    
    300
    +  pos.setLeft(pos.left() + sizeIndicatorOffset_);
    
    301
    +  painter->drawImage(pos, *image);
    
    302
    +  delete image;
    
    303
    +}
    
    304
    +
    
    305
    +
    
    288 306
     // end of glyphcontinuous.cpp

  • src/ftinspect/rendering/glyphcontinuous.hpp
    ... ... @@ -103,6 +103,9 @@ private:
    103 103
       void drawSingleGlyph(QPainter* painter,
    
    104 104
                            FT_Glyph glyph,
    
    105 105
                            FT_Vector penPos);
    
    106
    +  void drawSingleGlyphImage(QPainter* painter,
    
    107
    +                            QImage* image,
    
    108
    +                            QRect pos);
    
    106 109
     };
    
    107 110
     
    
    108 111
     
    


  • reply via email to

    [Prev in Thread] Current Thread [Next in Thread]