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] [ftinspect] WIP: Add


From: Charlie Jiang (@cqjjjzr)
Subject: [Git][freetype/freetype-demos][gsoc-2022-chariri-2] [ftinspect] WIP: Add LCD AntiAliasing and Bitmap font support.
Date: Wed, 13 Jul 2022 11:27:03 +0000

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

Commits:

  • 6e314154
    by Charlie Jiang at 2022-07-13T19:26:42+08:00
    [ftinspect] WIP: Add LCD AntiAliasing and Bitmap font support.
    
    WIP: NOT WORKING! Refer to the commit for detailed info.
    

17 changed files:

Changes:

  • src/ftinspect/engine/engine.cpp
    ... ... @@ -5,12 +5,16 @@
    5 5
     
    
    6 6
     #include "engine.hpp"
    
    7 7
     
    
    8
    +#include "../rendering/renderutils.hpp"
    
    9
    +#include "../rendering/graphicsdefault.hpp"
    
    10
    +
    
    8 11
     #include <stdexcept>
    
    9 12
     #include <stdint.h>
    
    10 13
     
    
    11 14
     #include <freetype/ftmodapi.h>
    
    12 15
     #include <freetype/ftdriver.h>
    
    13 16
     #include <freetype/ftlcdfil.h>
    
    17
    +#include <freetype/ftbitmap.h>
    
    14 18
     
    
    15 19
     
    
    16 20
     /////////////////////////////////////////////////////////////////////////////
    
    ... ... @@ -153,7 +157,7 @@ Engine::Engine()
    153 157
       {
    
    154 158
         // XXX error handling
    
    155 159
       }
    
    156
    -
    
    160
    +  
    
    157 161
       queryEngine();
    
    158 162
     }
    
    159 163
     
    
    ... ... @@ -397,8 +401,8 @@ Engine::glyphName(int index)
    397 401
     }
    
    398 402
     
    
    399 403
     
    
    400
    -FT_Outline*
    
    401
    -Engine::loadOutline(int glyphIndex)
    
    404
    +FT_Glyph
    
    405
    +Engine::loadGlyph(int glyphIndex)
    
    402 406
     {
    
    403 407
       update();
    
    404 408
     
    
    ... ... @@ -407,13 +411,11 @@ Engine::loadOutline(int glyphIndex)
    407 411
     
    
    408 412
       FT_Glyph glyph;
    
    409 413
     
    
    410
    -  // XXX handle bitmap fonts
    
    411
    -
    
    412 414
       // the `scaler' object is set up by the
    
    413 415
       // `update' and `loadFont' methods
    
    414 416
       if (FTC_ImageCache_LookupScaler(imageCache_,
    
    415 417
                                       &scaler_,
    
    416
    -                                  loadFlags_ | FT_LOAD_NO_BITMAP,
    
    418
    +                                  loadFlags_,
    
    417 419
                                       static_cast<unsigned int>(glyphIndex),
    
    418 420
                                       &glyph,
    
    419 421
                                       NULL))
    
    ... ... @@ -422,12 +424,7 @@ Engine::loadOutline(int glyphIndex)
    422 424
         return NULL;
    
    423 425
       }
    
    424 426
     
    
    425
    -  if (glyph->format != FT_GLYPH_FORMAT_OUTLINE)
    
    426
    -    return NULL;
    
    427
    -
    
    428
    -  FT_OutlineGlyph outlineGlyph = reinterpret_cast<FT_OutlineGlyph>(glyph);
    
    429
    -
    
    430
    -  return &outlineGlyph->outline;
    
    427
    +  return glyph;
    
    431 428
     }
    
    432 429
     
    
    433 430
     
    
    ... ... @@ -436,7 +433,8 @@ Engine::loadGlyphWithoutUpdate(int glyphIndex)
    436 433
     {
    
    437 434
       // TODO bitmap fonts? color layered fonts?
    
    438 435
       FT_Glyph glyph;
    
    439
    -  imageType_.flags |= FT_LOAD_NO_BITMAP;
    
    436
    +  if (!embeddedBitmap_)
    
    437
    +    imageType_.flags |= FT_LOAD_NO_BITMAP;
    
    440 438
       if (FTC_ImageCache_Lookup(imageCache_,
    
    441 439
                                 &imageType_,
    
    442 440
                                 glyphIndex,
    
    ... ... @@ -451,6 +449,63 @@ Engine::loadGlyphWithoutUpdate(int glyphIndex)
    451 449
     }
    
    452 450
     
    
    453 451
     
    
    452
    +bool
    
    453
    +Engine::glyphToBitmap(FT_Glyph src,
    
    454
    +                      FT_Glyph* out)
    
    455
    +{
    
    456
    +  if (src->format == FT_GLYPH_FORMAT_BITMAP)
    
    457
    +  {
    
    458
    +    *out = src;
    
    459
    +    return false;
    
    460
    +  }
    
    461
    +  if (src->format != FT_GLYPH_FORMAT_OUTLINE)
    
    462
    +  {
    
    463
    +    *out = NULL;
    
    464
    +    return false;
    
    465
    +    // TODO support SVG
    
    466
    +  }
    
    467
    +
    
    468
    +  if (src->format == FT_GLYPH_FORMAT_OUTLINE)
    
    469
    +  {
    
    470
    +    FT_Vector transformation = { 0, 0 };
    
    471
    +    auto outlineGlyph = reinterpret_cast<FT_OutlineGlyph>(src);
    
    472
    +    computeTransformationToOrigin(&outlineGlyph->outline,
    
    473
    +                                  &transformation.x,
    
    474
    +                                  &transformation.y,
    
    475
    +                                  NULL);
    
    476
    +    FT_Glyph out2 = src;
    
    477
    +    auto error = FT_Glyph_To_Bitmap(&out2, 
    
    478
    +                                    static_cast<FT_Render_Mode>(renderMode_),
    
    479
    +                                    &transformation,
    
    480
    +                                    false);
    
    481
    +    if (error)
    
    482
    +    {
    
    483
    +      *out = NULL;
    
    484
    +      return false;
    
    485
    +    }
    
    486
    +    *out = out2;
    
    487
    +    return true;
    
    488
    +  }
    
    489
    +
    
    490
    +  *out = NULL;
    
    491
    +  return false;
    
    492
    +}
    
    493
    +
    
    494
    +
    
    495
    +FT_Bitmap
    
    496
    +Engine::convertBitmapTo8Bpp(FT_Bitmap* bitmap)
    
    497
    +{
    
    498
    +  FT_Bitmap out;
    
    499
    +  out.buffer = NULL;
    
    500
    +  auto error = FT_Bitmap_Convert(library_, bitmap, &out, 1);
    
    501
    +  if (error)
    
    502
    +  {
    
    503
    +    // XXX handling?
    
    504
    +  }
    
    505
    +  return out;
    
    506
    +}
    
    507
    +
    
    508
    +
    
    454 509
     int
    
    455 510
     Engine::numberOfOpenedFonts()
    
    456 511
     {
    
    ... ... @@ -527,19 +582,19 @@ Engine::update()
    527 582
       loadFlags_ = FT_LOAD_DEFAULT;
    
    528 583
       if (doAutoHinting_)
    
    529 584
         loadFlags_ |= FT_LOAD_FORCE_AUTOHINT;
    
    530
    -  loadFlags_ |= FT_LOAD_NO_BITMAP; // XXX handle bitmap fonts also
    
    585
    +
    
    586
    +  if (!embeddedBitmap_)
    
    587
    +    loadFlags_ |= FT_LOAD_NO_BITMAP;
    
    531 588
     
    
    532 589
       if (doHinting_)
    
    533 590
       {
    
    534
    -    // TODO Differentiate RGB/BGR here?
    
    535
    -    unsigned long target = antiAliasingTarget_;
    
    536
    -    loadFlags_ |= target;
    
    591
    +    loadFlags_ |= antiAliasingTarget_;
    
    537 592
       }
    
    538 593
       else
    
    539 594
       {
    
    540 595
         loadFlags_ |= FT_LOAD_NO_HINTING;
    
    541 596
     
    
    542
    -    if (!antiAliasingEnabled_) // XXX does this hold?
    
    597
    +    if (!antiAliasingEnabled_)
    
    543 598
           loadFlags_ |= FT_LOAD_MONOCHROME;
    
    544 599
       }
    
    545 600
     
    
    ... ... @@ -561,7 +616,7 @@ Engine::update()
    561 616
         scaler_.x_res = dpi_;
    
    562 617
         scaler_.y_res = dpi_;
    
    563 618
       }
    
    564
    -  
    
    619
    +
    
    565 620
       imageType_.width = static_cast<unsigned int>(pixelSize_);
    
    566 621
       imageType_.height = static_cast<unsigned int>(pixelSize_);
    
    567 622
       imageType_.flags = static_cast<int>(loadFlags_);
    
    ... ... @@ -668,6 +723,197 @@ Engine::queryEngine()
    668 723
     }
    
    669 724
     
    
    670 725
     
    
    726
    +void
    
    727
    +convertLCDToARGB(FT_Bitmap& bitmap,
    
    728
    +                 QImage& image,
    
    729
    +                 bool isBGR)
    
    730
    +{
    
    731
    +  // see gblany.h
    
    732
    +  // Optimize me: Use SIMD?
    
    733
    +  int height = bitmap.rows;
    
    734
    +  int width = bitmap.width / 3;
    
    735
    +  int width3 = bitmap.width;
    
    736
    +
    
    737
    +  unsigned char* srcPtr = bitmap.buffer;
    
    738
    +  unsigned* dstPtr = reinterpret_cast<unsigned*>(image.bits());
    
    739
    +
    
    740
    +  int offR = !isBGR ? 0 : 2;
    
    741
    +  int offG = 1;
    
    742
    +  int offB = isBGR ? 0 : 2;
    
    743
    +  for (int i = 0; i < height; i++)
    
    744
    +  {
    
    745
    +    for (int j = 0; j < width3; j += 3)
    
    746
    +    {
    
    747
    +      unsigned char ar = srcPtr[j + offR];
    
    748
    +      unsigned char ag = srcPtr[j + offG];
    
    749
    +      unsigned char ab = srcPtr[j + offB];
    
    750
    +      *dstPtr = (0xFFU << 24) | (ar << 16) | (ag << 8) | ab;
    
    751
    +      dstPtr++;
    
    752
    +    }
    
    753
    +    srcPtr += bitmap.pitch;
    
    754
    +    dstPtr += image.bytesPerLine() / 4 - width; // skip blank area
    
    755
    +  }
    
    756
    +}
    
    757
    +
    
    758
    +
    
    759
    +void
    
    760
    +convertLCDVToARGB(FT_Bitmap& bitmap,
    
    761
    +                  QImage& image,
    
    762
    +                  bool isBGR)
    
    763
    +{
    
    764
    +  // see gblany.h
    
    765
    +  // Optimize me: Use SIMD?
    
    766
    +  int height = bitmap.rows / 3;
    
    767
    +  int width = bitmap.width;
    
    768
    +  int srcPitch = bitmap.pitch;
    
    769
    +
    
    770
    +  unsigned char* srcPtr = bitmap.buffer;
    
    771
    +  unsigned* dstPtr = reinterpret_cast<unsigned*>(image.bits());
    
    772
    +
    
    773
    +  int offR = !isBGR ? 0 : 2 * srcPitch;
    
    774
    +  int offG = srcPitch;
    
    775
    +  int offB = isBGR ? 0 : 2 * srcPitch;
    
    776
    +  for (int i = 0; i < height; i++)
    
    777
    +  {
    
    778
    +    for (int j = 0; j < width; j++)
    
    779
    +    {
    
    780
    +      unsigned char ar = srcPtr[j + offR];
    
    781
    +      unsigned char ag = srcPtr[j + offG];
    
    782
    +      unsigned char ab = srcPtr[j + offB];
    
    783
    +      *dstPtr = (0xFFU << 24) | (ar << 16) | (ag << 8) | ab;
    
    784
    +      dstPtr++;
    
    785
    +    }
    
    786
    +    srcPtr += 3ull * srcPitch;                  // move 3 lines
    
    787
    +    dstPtr += image.bytesPerLine() / 4 - width; // skip blank area
    
    788
    +  }
    
    789
    +}
    
    790
    +
    
    791
    +
    
    792
    +QImage*
    
    793
    +Engine::convertBitmapToQImage(FT_Glyph src,
    
    794
    +                              QRect* outRect)
    
    795
    +{
    
    796
    +  QImage* result = NULL;
    
    797
    +  FT_BitmapGlyph bitmapGlyph;
    
    798
    +  bool ownBitmapGlyph
    
    799
    +    = glyphToBitmap(src, reinterpret_cast<FT_Glyph*>(&bitmapGlyph));
    
    800
    +  if (!bitmapGlyph)
    
    801
    +    return result;
    
    802
    +  auto& bmap = bitmapGlyph->bitmap;
    
    803
    +  bool ownBitmap = false;
    
    804
    +
    
    805
    +  int width = bmap.width;
    
    806
    +  int height = bmap.rows;
    
    807
    +  QImage::Format format = QImage::Format_Indexed8; // goto crossing init
    
    808
    +
    
    809
    +  if (bmap.pixel_mode == FT_PIXEL_MODE_GRAY2
    
    810
    +      || bmap.pixel_mode == FT_PIXEL_MODE_GRAY4)
    
    811
    +  {
    
    812
    +    bmap = convertBitmapTo8Bpp(&bmap);
    
    813
    +    if (!bmap.buffer)
    
    814
    +      goto cleanup;
    
    815
    +    ownBitmap = true;
    
    816
    +  }
    
    817
    +
    
    818
    +  if (bmap.pixel_mode == FT_PIXEL_MODE_LCD)
    
    819
    +    width /= 3;
    
    820
    +  else if (bmap.pixel_mode == FT_PIXEL_MODE_LCD_V)
    
    821
    +    height /= 3;
    
    822
    +
    
    823
    +  if (outRect)
    
    824
    +  {
    
    825
    +    outRect->setLeft(bitmapGlyph->left);
    
    826
    +    outRect->setTop(-bitmapGlyph->top);
    
    827
    +    outRect->setWidth(width);
    
    828
    +    outRect->setHeight(height);
    
    829
    +  }
    
    830
    +
    
    831
    +  switch (bmap.pixel_mode)
    
    832
    +  {
    
    833
    +  case FT_PIXEL_MODE_MONO:
    
    834
    +    format = QImage::Format_Mono;
    
    835
    +    break;
    
    836
    +  case FT_PIXEL_MODE_GRAY:
    
    837
    +    format = QImage::Format_Indexed8;
    
    838
    +    break;
    
    839
    +  case FT_PIXEL_MODE_BGRA:
    
    840
    +    // XXX "ARGB" here means BGRA due to endianness - may be problematic
    
    841
    +    // on big-endian machines
    
    842
    +    format = QImage::Format_ARGB32_Premultiplied;
    
    843
    +    break;
    
    844
    +  case FT_PIXEL_MODE_LCD:
    
    845
    +  case FT_PIXEL_MODE_LCD_V:
    
    846
    +    format = QImage::Format_ARGB32;
    
    847
    +    break;
    
    848
    +  default:
    
    849
    +    goto cleanup;
    
    850
    +  }
    
    851
    +
    
    852
    +  switch (bmap.pixel_mode) 
    
    853
    +  {
    
    854
    +  case FT_PIXEL_MODE_MONO:
    
    855
    +  case FT_PIXEL_MODE_GRAY:
    
    856
    +  case FT_PIXEL_MODE_BGRA:
    
    857
    +    {
    
    858
    +      QImage image(bmap.buffer, 
    
    859
    +                   width, height, 
    
    860
    +                   bmap.pitch, 
    
    861
    +                   format);
    
    862
    +      if (bmap.pixel_mode == FT_PIXEL_MODE_GRAY)
    
    863
    +        image.setColorTable(GraphicsDefault::deafultInstance()->grayColorTable);
    
    864
    +      else if (bmap.pixel_mode == FT_PIXEL_MODE_MONO)
    
    865
    +        image.setColorTable(GraphicsDefault::deafultInstance()->monoColorTable);
    
    866
    +      result = new QImage(image.copy());
    
    867
    +      // Don't directly use `image` since we're destroying the image
    
    868
    +    }
    
    869
    +    break;
    
    870
    +  case FT_PIXEL_MODE_LCD:;
    
    871
    +    result = new QImage(width, height, format);
    
    872
    +    convertLCDToARGB(bmap, *result, lcdUsesBGR_);
    
    873
    +    break;
    
    874
    +  case FT_PIXEL_MODE_LCD_V:;
    
    875
    +    result = new QImage(width, height, format);
    
    876
    +    convertLCDVToARGB(bmap, *result, lcdUsesBGR_);
    
    877
    +    break;
    
    878
    +  }
    
    879
    +
    
    880
    +cleanup:
    
    881
    +  if (ownBitmapGlyph)
    
    882
    +    FT_Done_Glyph(reinterpret_cast<FT_Glyph>(bitmapGlyph));
    
    883
    +  if (ownBitmap)
    
    884
    +    FT_Bitmap_Done(library_, &bmap);
    
    885
    +
    
    886
    +  return result;
    
    887
    +}
    
    888
    +
    
    889
    +
    
    890
    +QHash<FT_Glyph_Format, QString> glyphFormatNamesCache;
    
    891
    +QHash<FT_Glyph_Format, QString>&
    
    892
    +glyphFormatNames()
    
    893
    +{
    
    894
    +  if (glyphFormatNamesCache.empty())
    
    895
    +  {
    
    896
    +    glyphFormatNamesCache[FT_GLYPH_FORMAT_NONE] = "None/Unknown";
    
    897
    +    glyphFormatNamesCache[FT_GLYPH_FORMAT_COMPOSITE] = "Composite";
    
    898
    +    glyphFormatNamesCache[FT_GLYPH_FORMAT_BITMAP] = "Bitmap";
    
    899
    +    glyphFormatNamesCache[FT_GLYPH_FORMAT_OUTLINE] = "Outline";
    
    900
    +    glyphFormatNamesCache[FT_GLYPH_FORMAT_PLOTTER] = "Plotter";
    
    901
    +    glyphFormatNamesCache[FT_GLYPH_FORMAT_SVG] = "SVG";
    
    902
    +  }
    
    903
    +  return glyphFormatNamesCache;
    
    904
    +}
    
    905
    +
    
    906
    +QString*
    
    907
    +glyphFormatToName(FT_Glyph_Format format)
    
    908
    +{
    
    909
    +  auto& names = glyphFormatNames();
    
    910
    +  auto it = names.find(format);
    
    911
    +  if (it == names.end())
    
    912
    +    return &names[FT_GLYPH_FORMAT_NONE];
    
    913
    +  return &it.value();
    
    914
    +}
    
    915
    +
    
    916
    +
    
    671 917
     QHash<FT_Encoding, QString> encodingNamesCache;
    
    672 918
     QHash<FT_Encoding, QString>&
    
    673 919
     encodingNames()
    

  • src/ftinspect/engine/engine.hpp
    ... ... @@ -10,6 +10,8 @@
    10 10
     #include <vector>
    
    11 11
     #include <QString>
    
    12 12
     #include <QMap>
    
    13
    +#include <QRect>
    
    14
    +#include <QImage>
    
    13 15
     
    
    14 16
     #include <ft2build.h>
    
    15 17
     #include <freetype/freetype.h>
    
    ... ... @@ -60,6 +62,10 @@ private:
    60 62
       static int maxIndexForFaceAndCharMap(FT_CharMap charMap, unsigned max);
    
    61 63
     };
    
    62 64
     
    
    65
    +// Some helper functions.
    
    66
    +
    
    67
    +QString* glyphFormatToName(FT_Glyph_Format format);
    
    68
    +
    
    63 69
     // FreeType specific data.
    
    64 70
     
    
    65 71
     class Engine
    
    ... ... @@ -92,11 +98,18 @@ public:
    92 98
       int loadFont(int fontIndex,
    
    93 99
                    long faceIndex,
    
    94 100
                    int namedInstanceIndex); // return number of glyphs
    
    95
    -  FT_Outline* loadOutline(int glyphIndex);
    
    101
    +  //FT_Outline* loadOutline(int glyphIndex);
    
    102
    +  FT_Glyph loadGlyph(int glyphIndex);
    
    96 103
     
    
    97 104
       // Sometimes the engine is already updated, and we want to be faster
    
    98 105
       FT_Glyph loadGlyphWithoutUpdate(int glyphIndex);
    
    99 106
     
    
    107
    +  // Return `true` if you need to free `out`
    
    108
    +  // `out` will be set to NULL in cases of error
    
    109
    +  bool glyphToBitmap(FT_Glyph src, FT_Glyph* out);
    
    110
    +  FT_Bitmap convertBitmapTo8Bpp(FT_Bitmap* bitmap);
    
    111
    +  QImage* convertBitmapToQImage(FT_Glyph src, QRect* outRect);
    
    112
    +
    
    100 113
       // reload current triplet, but with updated settings, useful for updating
    
    101 114
       // `ftSize_` only
    
    102 115
       void reloadFont(); 
    
    ... ... @@ -126,7 +139,7 @@ public:
    126 139
       FontFileManager& fontFileManager() { return fontFileManager_; }
    
    127 140
       EngineDefaultValues& engineDefaults() { return engineDefaults_; }
    
    128 141
       bool antiAliasingEnabled() { return antiAliasingEnabled_; }
    
    129
    -
    
    142
    +  bool embeddedBitmapEnabled() { return embeddedBitmap_; }
    
    130 143
     
    
    131 144
       //////// Setters (direct or indirect)
    
    132 145
     
    
    ... ... @@ -150,7 +163,10 @@ public:
    150 163
       void setShowSegments(bool showSegments) { showSegments_ = showSegments; }
    
    151 164
       void setGamma(double gamma) { gamma_ = gamma; }
    
    152 165
       void setAntiAliasingTarget(int target) { antiAliasingTarget_ = target; }
    
    166
    +  void setRenderMode(int mode) { renderMode_ = mode; }
    
    153 167
       void setAntiAliasingEnabled(bool enabled) { antiAliasingEnabled_ = enabled; }
    
    168
    +  void setEmbeddedBitmap(bool force) { embeddedBitmap_ = force; }
    
    169
    +  void setLCDUsesBGR(bool isBGR) { lcdUsesBGR_ = isBGR; }
    
    154 170
     
    
    155 171
       // Note: These 3 functions now takes actual mode/version from FreeType,
    
    156 172
       // instead of values from enum in MainGUI!
    
    ... ... @@ -203,10 +219,12 @@ private:
    203 219
       bool doVerticalHinting_;
    
    204 220
       bool doBlueZoneHinting_;
    
    205 221
       bool showSegments_;
    
    222
    +  bool embeddedBitmap_;
    
    206 223
       int antiAliasingTarget_;
    
    224
    +  bool lcdUsesBGR_;
    
    225
    +  int renderMode_;
    
    207 226
     
    
    208 227
       double gamma_;
    
    209
    -
    
    210 228
       unsigned long loadFlags_;
    
    211 229
     
    
    212 230
       void queryEngine();
    

  • src/ftinspect/models/ttsettingscomboboxmodel.cpp
    ... ... @@ -190,48 +190,6 @@ HintingModeComboBoxModel::setCurrentEngineType(HintingEngineType type)
    190 190
     }
    
    191 191
     
    
    192 192
     
    
    193
    -/////////////////////////////////////////////////////////////////////////////
    
    194
    -//
    
    195
    -// SimpleComboBoxModel
    
    196
    -//
    
    197
    -/////////////////////////////////////////////////////////////////////////////
    
    198
    -
    
    199
    -
    
    200
    -SimpleComboBoxModel::SimpleComboBoxModel(QObject* parent)
    
    201
    -: QAbstractListModel(parent)
    
    202
    -{
    
    203
    -}
    
    204
    -
    
    205
    -
    
    206
    -int
    
    207
    -SimpleComboBoxModel::rowCount(const QModelIndex& parent) const
    
    208
    -{
    
    209
    -  return items_.size();
    
    210
    -}
    
    211
    -
    
    212
    -
    
    213
    -QVariant
    
    214
    -SimpleComboBoxModel::data(const QModelIndex& index, int role) const
    
    215
    -{
    
    216
    -  if (role != Qt::DisplayRole)
    
    217
    -    return QVariant {};
    
    218
    -
    
    219
    -  int r = index.row();
    
    220
    -  if (r < 0 || r >= items_.size())
    
    221
    -    return QVariant {};
    
    222
    -  return items_[r].displayName;
    
    223
    -}
    
    224
    -
    
    225
    -
    
    226
    -int
    
    227
    -SimpleComboBoxModel::indexToValue(int index)
    
    228
    -{
    
    229
    -  if (index < 0 || index >= items_.size())
    
    230
    -    return -1;
    
    231
    -  return items_[index].value;
    
    232
    -}
    
    233
    -
    
    234
    -
    
    235 193
     /////////////////////////////////////////////////////////////////////////////
    
    236 194
     //
    
    237 195
     // LCDFilterComboBoxModel
    
    ... ... @@ -240,7 +198,7 @@ SimpleComboBoxModel::indexToValue(int index)
    240 198
     
    
    241 199
     
    
    242 200
     LCDFilterComboBoxModel::LCDFilterComboBoxModel(QObject* parent)
    
    243
    -: SimpleComboBoxModel(parent)
    
    201
    +: QAbstractListModel(parent)
    
    244 202
     {
    
    245 203
       items_[LCDFilter_Default] = {
    
    246 204
         FT_LCD_FILTER_DEFAULT,
    
    ... ... @@ -269,34 +227,34 @@ LCDFilterComboBoxModel::LCDFilterComboBoxModel(QObject* parent)
    269 227
     
    
    270 228
     
    
    271 229
     AntiAliasingComboBoxModel::AntiAliasingComboBoxModel(QObject* parent)
    
    272
    -: SimpleComboBoxModel(parent)
    
    230
    +: QAbstractListModel(parent)
    
    273 231
     {
    
    274 232
       items_[AntiAliasing_None] = {
    
    275
    -    FT_LOAD_TARGET_MONO,
    
    233
    +    {FT_LOAD_TARGET_MONO, FT_RENDER_MODE_MONO},
    
    276 234
         "None"
    
    277 235
       };
    
    278 236
       items_[AntiAliasing_Normal] = {
    
    279
    -    FT_LOAD_TARGET_NORMAL,
    
    237
    +    {FT_LOAD_TARGET_NORMAL, FT_RENDER_MODE_NORMAL},
    
    280 238
         "Normal"
    
    281 239
       };
    
    282 240
       items_[AntiAliasing_Light] = {
    
    283
    -    FT_LOAD_TARGET_LIGHT,
    
    241
    +    {FT_LOAD_TARGET_LIGHT, FT_RENDER_MODE_LIGHT},
    
    284 242
         "Light"
    
    285 243
       };
    
    286 244
       items_[AntiAliasing_LCD] = {
    
    287
    -    FT_LOAD_TARGET_LCD,
    
    245
    +    {FT_LOAD_TARGET_LCD, FT_RENDER_MODE_LCD},
    
    288 246
         "LCD (RGB)"
    
    289 247
       };
    
    290 248
       items_[AntiAliasing_LCD_BGR] = {
    
    291
    -    FT_LOAD_TARGET_LCD,
    
    249
    +    {FT_LOAD_TARGET_LCD, FT_RENDER_MODE_LCD, true},
    
    292 250
         "LCD (BGR)"
    
    293 251
       };
    
    294 252
       items_[AntiAliasing_LCD_Vertical] = {
    
    295
    -    FT_LOAD_TARGET_LCD_V,
    
    253
    +    {FT_LOAD_TARGET_LCD_V, FT_RENDER_MODE_LCD_V},
    
    296 254
         "LCD (vert. RGB)"
    
    297 255
       };
    
    298 256
       items_[AntiAliasing_LCD_Vertical_BGR] = {
    
    299
    -    FT_LOAD_TARGET_LCD_V, // XXX Bug: No difference between RGB and BGR?
    
    257
    +    {FT_LOAD_TARGET_LCD_V, FT_RENDER_MODE_LCD_V, true},
    
    300 258
         "LCD (vert. BGR)"
    
    301 259
       };
    
    302 260
     
    
    ... ... @@ -312,7 +270,7 @@ AntiAliasingComboBoxModel::data(const QModelIndex& index,
    312 270
         if (index.row() == AntiAliasing_Light && !lightAntiAliasingEnabled_)
    
    313 271
           return QApplication::palette().color(QPalette::Disabled, 
    
    314 272
                                                QPalette::Text);
    
    315
    -  return SimpleComboBoxModel::data(index, role);
    
    273
    +  return SimpleComboBoxModelImpl::data(index, role);
    
    316 274
     }
    
    317 275
     
    
    318 276
     
    

  • src/ftinspect/models/ttsettingscomboboxmodel.hpp
    ... ... @@ -71,25 +71,45 @@ public:
    71 71
     
    
    72 72
     
    
    73 73
     // A simple key-displayName-value model for QComboBox.
    
    74
    -class SimpleComboBoxModel
    
    75
    -: public QAbstractListModel
    
    74
    +template <class T>
    
    75
    +class SimpleComboBoxModelImpl
    
    76 76
     {
    
    77
    -  Q_OBJECT
    
    78 77
     public:
    
    79 78
       struct ComboBoxItem
    
    80 79
       {
    
    81
    -    int value;
    
    80
    +    T value;
    
    82 81
         QString displayName;
    
    83 82
       };
    
    84 83
     
    
    85
    -  explicit SimpleComboBoxModel(QObject* parent);
    
    86
    -  ~SimpleComboBoxModel() override = default;
    
    84
    +  SimpleComboBoxModelImpl() {}
    
    85
    +  ~SimpleComboBoxModelImpl() = default;
    
    87 86
     
    
    88
    -  int rowCount(const QModelIndex& parent) const;
    
    89
    -  QVariant data(const QModelIndex& index,
    
    90
    -                int role) const;
    
    87
    +  virtual int
    
    88
    +  rowCount(const QModelIndex& parent) const
    
    89
    +  {
    
    90
    +    return items_.size();
    
    91
    +  }
    
    92
    +
    
    93
    +  virtual QVariant
    
    94
    +  data(const QModelIndex& index,
    
    95
    +                int role) const
    
    96
    +  {
    
    97
    +    if (role != Qt::DisplayRole)
    
    98
    +      return QVariant{};
    
    91 99
     
    
    92
    -  int indexToValue(int index);
    
    100
    +    int r = index.row();
    
    101
    +    if (r < 0 || r >= items_.size())
    
    102
    +      return QVariant{};
    
    103
    +    return items_[r].displayName;
    
    104
    +  }
    
    105
    +
    
    106
    +  virtual T
    
    107
    +  indexToValue(int index)
    
    108
    +  {
    
    109
    +    if (index < 0 || index >= items_.size())
    
    110
    +      return T();
    
    111
    +    return items_[index].value;
    
    112
    +  }
    
    93 113
     
    
    94 114
     protected:
    
    95 115
       QHash<int, ComboBoxItem> items_;
    
    ... ... @@ -97,7 +117,8 @@ protected:
    97 117
     
    
    98 118
     
    
    99 119
     class LCDFilterComboBoxModel
    
    100
    -: public SimpleComboBoxModel
    
    120
    +: public QAbstractListModel,
    
    121
    +  public SimpleComboBoxModelImpl<int>
    
    101 122
     {
    
    102 123
       Q_OBJECT
    
    103 124
     public:
    
    ... ... @@ -111,6 +132,17 @@ public:
    111 132
       explicit LCDFilterComboBoxModel(QObject* parent);
    
    112 133
       virtual ~LCDFilterComboBoxModel() = default;
    
    113 134
     
    
    135
    +  int rowCount(const QModelIndex& parent) const override
    
    136
    +  {
    
    137
    +    return SimpleComboBoxModelImpl::rowCount(parent);
    
    138
    +  }
    
    139
    +  QVariant
    
    140
    +  data(const QModelIndex& index,
    
    141
    +       int role) const override
    
    142
    +  {
    
    143
    +    return SimpleComboBoxModelImpl::data(index, role);
    
    144
    +  }
    
    145
    +
    
    114 146
     public:
    
    115 147
       enum LCDFilter : int
    
    116 148
       {
    
    ... ... @@ -122,8 +154,17 @@ public:
    122 154
     };
    
    123 155
     
    
    124 156
     
    
    157
    +struct AASetting
    
    158
    +{
    
    159
    +  int lcdFilter = -1;
    
    160
    +  int renderMode = -1;
    
    161
    +  bool isBGR = false;
    
    162
    +};
    
    163
    +
    
    164
    +
    
    125 165
     class AntiAliasingComboBoxModel
    
    126
    -: public SimpleComboBoxModel
    
    166
    +: public QAbstractListModel,
    
    167
    +  public SimpleComboBoxModelImpl<AASetting>
    
    127 168
     {
    
    128 169
       Q_OBJECT
    
    129 170
     public:
    
    ... ... @@ -135,6 +176,11 @@ public:
    135 176
       QVariant data(const QModelIndex& index,
    
    136 177
                     int role) const;
    
    137 178
       Qt::ItemFlags flags(const QModelIndex& index) const;
    
    179
    +  using SimpleComboBoxModelImpl::rowCount;
    
    180
    +  int rowCount(const QModelIndex& parent) const override
    
    181
    +  {
    
    182
    +    return SimpleComboBoxModelImpl::rowCount(parent);
    
    183
    +  }
    
    138 184
     
    
    139 185
       void setLightAntiAliasingEnabled(bool enabled)
    
    140 186
       {
    

  • src/ftinspect/panels/settingpanel.cpp
    ... ... @@ -172,8 +172,12 @@ SettingPanel::syncSettings()
    172 172
       engine_->setLcdFilter(
    
    173 173
         static_cast<FT_LcdFilter>(lcdFilterComboboxModel_->indexToValue(
    
    174 174
           lcdFilterComboBox_->currentIndex())));
    
    175
    -  engine_->setAntiAliasingTarget(antiAliasingComboBoxModel_->indexToValue(
    
    176
    -    antiAliasingComboBox_->currentIndex()));
    
    175
    +
    
    176
    +  auto aaSettings = antiAliasingComboBoxModel_->indexToValue(
    
    177
    +    antiAliasingComboBox_->currentIndex());
    
    178
    +  engine_->setAntiAliasingTarget(aaSettings.lcdFilter);
    
    179
    +  engine_->setRenderMode(aaSettings.renderMode);
    
    180
    +
    
    177 181
       engine_->setAntiAliasingEnabled(antiAliasingComboBox_->currentIndex()
    
    178 182
         != AntiAliasingComboBoxModel::AntiAliasing_None);
    
    179 183
       engine_->setHinting(hintingCheckBox_->isChecked());
    
    ... ... @@ -184,6 +188,9 @@ SettingPanel::syncSettings()
    184 188
       engine_->setShowSegments(segmentDrawingCheckBox_->isChecked());
    
    185 189
     
    
    186 190
       engine_->setGamma(gammaSlider_->value());
    
    191
    +
    
    192
    +  engine_->setEmbeddedBitmap(embeddedBitmapCheckBox_->isChecked());
    
    193
    +  engine_->setLCDUsesBGR(aaSettings.isBGR);
    
    187 194
     }
    
    188 195
     
    
    189 196
     
    
    ... ... @@ -218,6 +225,8 @@ SettingPanel::createConnections()
    218 225
     
    
    219 226
       connect(autoHintingCheckBox_, &QCheckBox::clicked,
    
    220 227
               this, &SettingPanel::checkAutoHinting);
    
    228
    +  connect(embeddedBitmapCheckBox_, &QCheckBox::clicked,
    
    229
    +          this, &SettingPanel::repaintNeeded);
    
    221 230
     }
    
    222 231
     
    
    223 232
     
    
    ... ... @@ -239,6 +248,7 @@ SettingPanel::createLayout()
    239 248
       verticalHintingCheckBox_ = new QCheckBox(tr("Vertical Hinting"), this);
    
    240 249
       blueZoneHintingCheckBox_ = new QCheckBox(tr("Blue-Zone Hinting"), this);
    
    241 250
       segmentDrawingCheckBox_ = new QCheckBox(tr("Segment Drawing"), this);
    
    251
    +  embeddedBitmapCheckBox_ = new QCheckBox(tr("Enable Embedded Bitmap"), this);
    
    242 252
     
    
    243 253
       antiAliasingLabel_ = new QLabel(tr("Anti-Aliasing"), this);
    
    244 254
       antiAliasingLabel_->setAlignment(Qt::AlignRight);
    
    ... ... @@ -329,6 +339,7 @@ SettingPanel::createLayout()
    329 339
       generalTabLayout_->addSpacing(20); // XXX px
    
    330 340
       generalTabLayout_->addStretch(1);
    
    331 341
       generalTabLayout_->addLayout(gammaLayout_);
    
    342
    +  generalTabLayout_->addWidget(embeddedBitmapCheckBox_);
    
    332 343
       generalTabLayout_->addSpacing(20); // XXX px
    
    333 344
       generalTabLayout_->addStretch(1);
    
    334 345
     
    
    ... ... @@ -376,6 +387,7 @@ SettingPanel::setDefaults()
    376 387
       horizontalHintingCheckBox_->setChecked(true);
    
    377 388
       verticalHintingCheckBox_->setChecked(true);
    
    378 389
       blueZoneHintingCheckBox_->setChecked(true);
    
    390
    +  embeddedBitmapCheckBox_->setChecked(false);
    
    379 391
     
    
    380 392
       gammaSlider_->setValue(18); // 1.8
    
    381 393
     }
    

  • src/ftinspect/panels/settingpanel.hpp
    ... ... @@ -63,6 +63,7 @@ private:
    63 63
       QCheckBox* blueZoneHintingCheckBox_;
    
    64 64
       QCheckBox* segmentDrawingCheckBox_;
    
    65 65
       QCheckBox* autoHintingCheckBox_;
    
    66
    +  QCheckBox* embeddedBitmapCheckBox_;
    
    66 67
     
    
    67 68
       AntiAliasingComboBoxModel* antiAliasingComboBoxModel_;
    
    68 69
       HintingModeComboBoxModel* hintingModeComboBoxModel_;
    

  • src/ftinspect/panels/singular.cpp
    ... ... @@ -87,29 +87,21 @@ SingularTab::drawGlyph()
    87 87
       }
    
    88 88
     
    
    89 89
       syncSettings();
    
    90
    -  FT_Outline* outline = engine_->loadOutline(currentGlyphIndex_);
    
    91
    -  if (outline)
    
    90
    +  FT_Glyph glyph = engine_->loadGlyph(currentGlyphIndex_);
    
    91
    +  if (glyph)
    
    92 92
       {
    
    93 93
         if (showBitmapCheckBox_->isChecked())
    
    94 94
         {
    
    95
    -      // XXX support LCD
    
    96
    -      FT_Pixel_Mode pixelMode = FT_PIXEL_MODE_GRAY;
    
    97
    -      if (!engine_->antiAliasingEnabled())
    
    98
    -        pixelMode = FT_PIXEL_MODE_MONO;
    
    99
    -
    
    100 95
           currentGlyphBitmapItem_
    
    101
    -        = new GlyphBitmap(outline,
    
    102
    -          engine_->ftLibrary(),
    
    103
    -          pixelMode,
    
    104
    -          graphicsDefault_->monoColorTable,
    
    105
    -          graphicsDefault_->grayColorTable);
    
    96
    +        = new GlyphBitmap(glyph,
    
    97
    +                          engine_);
    
    106 98
           glyphScene_->addItem(currentGlyphBitmapItem_);
    
    107 99
         }
    
    108 100
     
    
    109 101
         if (showOutlinesCheckBox_->isChecked())
    
    110 102
         {
    
    111 103
           currentGlyphOutlineItem_ = new GlyphOutline(graphicsDefault_->outlinePen, 
    
    112
    -                                                  outline);
    
    104
    +                                                  glyph);
    
    113 105
           glyphScene_->addItem(currentGlyphOutlineItem_);
    
    114 106
         }
    
    115 107
     
    
    ... ... @@ -117,7 +109,7 @@ SingularTab::drawGlyph()
    117 109
         {
    
    118 110
           currentGlyphPointsItem_ = new GlyphPoints(graphicsDefault_->onPen,
    
    119 111
                                                     graphicsDefault_->offPen,
    
    120
    -                                                outline);
    
    112
    +                                                glyph);
    
    121 113
           glyphScene_->addItem(currentGlyphPointsItem_);
    
    122 114
     
    
    123 115
           if (showPointNumbersCheckBox_->isChecked())
    
    ... ... @@ -125,7 +117,7 @@ SingularTab::drawGlyph()
    125 117
             currentGlyphPointNumbersItem_
    
    126 118
               = new GlyphPointNumbers(graphicsDefault_->onPen,
    
    127 119
                                       graphicsDefault_->offPen,
    
    128
    -                                  outline);
    
    120
    +                                  glyph);
    
    129 121
             glyphScene_->addItem(currentGlyphPointNumbersItem_);
    
    130 122
           }
    
    131 123
         }
    

  • src/ftinspect/rendering/glyphbitmap.cpp
    ... ... @@ -6,34 +6,27 @@
    6 6
     #include "glyphbitmap.hpp"
    
    7 7
     
    
    8 8
     #include "renderutils.hpp"
    
    9
    +#include "../engine/engine.hpp"
    
    9 10
     
    
    10 11
     #include <cmath>
    
    11 12
     #include <QPainter>
    
    12 13
     #include <QStyleOptionGraphicsItem>
    
    14
    +#include <freetype/ftbitmap.h>
    
    13 15
     
    
    14 16
     
    
    15
    -GlyphBitmap::GlyphBitmap(FT_Outline* outline,
    
    16
    -                         FT_Library lib,
    
    17
    -                         FT_Pixel_Mode pxlMode,
    
    18
    -                         const QVector<QRgb>& monoColorTbl,
    
    19
    -                         const QVector<QRgb>& grayColorTbl)
    
    20
    -: library_(lib),
    
    21
    -  pixelMode_(pxlMode),
    
    22
    -  monoColorTable_(monoColorTbl),
    
    23
    -  grayColorTable_(grayColorTbl)
    
    17
    +GlyphBitmap::GlyphBitmap(FT_Glyph glyph,
    
    18
    +                         Engine* engine)
    
    19
    +: engine_(engine),
    
    20
    +  library_(engine->ftLibrary())
    
    24 21
     {
    
    25
    -  // make a copy of the outline since we are going to manipulate it
    
    26
    -  FT_BBox cbox;
    
    27
    -  transformed_ = cloneOutline(lib, outline);
    
    28
    -  transformOutlineToOrigin(&transformed_, &cbox);
    
    29
    -  boundingRect_.setCoords(cbox.xMin / 64, -cbox.yMax / 64,
    
    30
    -                  cbox.xMax / 64, -cbox.yMin / 64);
    
    22
    +  QRect bRect;
    
    23
    +  image_ = engine_->convertBitmapToQImage(glyph, &bRect);
    
    24
    +  boundingRect_ = bRect; // QRectF to QRect
    
    31 25
     }
    
    32 26
     
    
    33 27
     
    
    34 28
     GlyphBitmap::~GlyphBitmap()
    
    35 29
     {
    
    36
    -  FT_Outline_Done(library_, &transformed_);
    
    37 30
     }
    
    38 31
     
    
    39 32
     QRectF
    
    ... ... @@ -48,40 +41,9 @@ GlyphBitmap::paint(QPainter* painter,
    48 41
                        const QStyleOptionGraphicsItem* option,
    
    49 42
                        QWidget*)
    
    50 43
     {
    
    51
    -  FT_Bitmap bitmap;
    
    52
    -
    
    53
    -  int height = static_cast<int>(ceil(boundingRect_.height()));
    
    54
    -  int width = static_cast<int>(ceil(boundingRect_.width()));
    
    55
    -  QImage::Format format = QImage::Format_Indexed8;
    
    56
    -
    
    57
    -  // XXX cover LCD and color
    
    58
    -  if (pixelMode_ == FT_PIXEL_MODE_MONO)
    
    59
    -    format = QImage::Format_Mono;
    
    60
    -
    
    61
    -  QImage image(QSize(width, height), format);
    
    62
    -
    
    63
    -  if (pixelMode_ == FT_PIXEL_MODE_MONO)
    
    64
    -    image.setColorTable(monoColorTable_);
    
    65
    -  else
    
    66
    -    image.setColorTable(grayColorTable_);
    
    67
    -
    
    68
    -  image.fill(0);
    
    69
    -
    
    70
    -  bitmap.rows = static_cast<unsigned int>(height);
    
    71
    -  bitmap.width = static_cast<unsigned int>(width);
    
    72
    -  bitmap.buffer = image.bits();
    
    73
    -  bitmap.pitch = image.bytesPerLine();
    
    74
    -  bitmap.pixel_mode = pixelMode_;
    
    75
    -
    
    76
    -  FT_Error error = FT_Outline_Get_Bitmap(library_,
    
    77
    -                                         &transformed_,
    
    78
    -                                         &bitmap);
    
    79
    -  if (error)
    
    80
    -  {
    
    81
    -    // XXX error handling
    
    44
    +  if (!image_)
    
    82 45
         return;
    
    83
    -  }
    
    84
    -
    
    46
    +  
    
    85 47
       // `drawImage' doesn't work as expected:
    
    86 48
       // the larger the zoom, the more the pixel rectangle positions
    
    87 49
       // deviate from the grid lines
    
    ... ... @@ -95,11 +57,11 @@ GlyphBitmap::paint(QPainter* painter,
    95 57
     
    
    96 58
       painter->setPen(Qt::NoPen);
    
    97 59
     
    
    98
    -  for (int x = 0; x < image.width(); x++)
    
    99
    -    for (int y = 0; y < image.height(); y++)
    
    60
    +  for (int x = 0; x < image_->width(); x++)
    
    61
    +    for (int y = 0; y < image_->height(); y++)
    
    100 62
         {
    
    101 63
           // be careful not to lose the alpha channel
    
    102
    -      QRgb p = image.pixel(x, y);
    
    64
    +      QRgb p = image_->pixel(x, y);
    
    103 65
           painter->fillRect(QRectF(x + boundingRect_.left() - 1 / lod / 2,
    
    104 66
                                    y + boundingRect_.top() - 1 / lod / 2,
    
    105 67
                                    1 + 1 / lod,
    
    ... ... @@ -109,7 +71,9 @@ GlyphBitmap::paint(QPainter* painter,
    109 71
                                    qBlue(p),
    
    110 72
                                    qAlpha(p)));
    
    111 73
         }
    
    74
    +    
    
    112 75
     #endif
    
    76
    +
    
    113 77
     }
    
    114 78
     
    
    115 79
     
    

  • src/ftinspect/rendering/glyphbitmap.hpp
    ... ... @@ -10,18 +10,18 @@
    10 10
     
    
    11 11
     #include <ft2build.h>
    
    12 12
     #include <freetype/freetype.h>
    
    13
    +#include <freetype/ftglyph.h>
    
    13 14
     #include <freetype/ftoutln.h>
    
    14 15
     
    
    15 16
     
    
    17
    +class Engine;
    
    18
    +
    
    16 19
     class GlyphBitmap
    
    17 20
     : public QGraphicsItem
    
    18 21
     {
    
    19 22
     public:
    
    20
    -  GlyphBitmap(FT_Outline* outline,
    
    21
    -              FT_Library library,
    
    22
    -              FT_Pixel_Mode pixelMode,
    
    23
    -              const QVector<QRgb>& monoColorTable,
    
    24
    -              const QVector<QRgb>& grayColorTable);
    
    23
    +  GlyphBitmap(FT_Glyph glyph,
    
    24
    +              Engine* engine);
    
    25 25
       ~GlyphBitmap() override;
    
    26 26
       QRectF boundingRect() const override;
    
    27 27
       void paint(QPainter* painter,
    
    ... ... @@ -29,11 +29,9 @@ public:
    29 29
                  QWidget* widget) override;
    
    30 30
     
    
    31 31
     private:
    
    32
    -  FT_Outline transformed_;
    
    32
    +  Engine* engine_;
    
    33
    +  QImage* image_ = NULL;
    
    33 34
       FT_Library library_;
    
    34
    -  unsigned char pixelMode_;
    
    35
    -  const QVector<QRgb>& monoColorTable_;
    
    36
    -  const QVector<QRgb>& grayColorTable_;
    
    37 35
       QRectF boundingRect_;
    
    38 36
     };
    
    39 37
     
    

  • src/ftinspect/rendering/glyphoutline.cpp
    ... ... @@ -88,10 +88,16 @@ static FT_Outline_Funcs outlineFuncs =
    88 88
     
    
    89 89
     
    
    90 90
     GlyphOutline::GlyphOutline(const QPen& pen,
    
    91
    -                           FT_Outline* outline)
    
    92
    -: outlinePen_(pen),
    
    93
    -  outline_(outline)
    
    91
    +                           FT_Glyph glyph)
    
    92
    +: outlinePen_(pen)
    
    94 93
     {
    
    94
    +  if (glyph->format != FT_GLYPH_FORMAT_OUTLINE)
    
    95
    +  {
    
    96
    +    outline_ = NULL;
    
    97
    +    return;
    
    98
    +  }
    
    99
    +  outline_ = &reinterpret_cast<FT_OutlineGlyph>(glyph)->outline;
    
    100
    +
    
    95 101
       FT_BBox cbox;
    
    96 102
     
    
    97 103
       qreal halfPenWidth = outlinePen_.widthF();
    
    ... ... @@ -117,6 +123,8 @@ GlyphOutline::paint(QPainter* painter,
    117 123
                         const QStyleOptionGraphicsItem*,
    
    118 124
                         QWidget*)
    
    119 125
     {
    
    126
    +  if (!outline_)
    
    127
    +    return;
    
    120 128
       painter->setPen(outlinePen_);
    
    121 129
     
    
    122 130
       QPainterPath path;
    

  • src/ftinspect/rendering/glyphoutline.hpp
    ... ... @@ -10,6 +10,7 @@
    10 10
     
    
    11 11
     #include <ft2build.h>
    
    12 12
     #include <freetype/freetype.h>
    
    13
    +#include <freetype/ftglyph.h>
    
    13 14
     #include <freetype/ftoutln.h>
    
    14 15
     
    
    15 16
     
    
    ... ... @@ -18,7 +19,7 @@ class GlyphOutline
    18 19
     {
    
    19 20
     public:
    
    20 21
       GlyphOutline(const QPen& pen,
    
    21
    -               FT_Outline* outline);
    
    22
    +               FT_Glyph glyph);
    
    22 23
       QRectF boundingRect() const override;
    
    23 24
       void paint(QPainter* painter,
    
    24 25
                  const QStyleOptionGraphicsItem* option,
    

  • src/ftinspect/rendering/glyphpointnumbers.cpp
    ... ... @@ -12,11 +12,17 @@
    12 12
     
    
    13 13
     GlyphPointNumbers::GlyphPointNumbers(const QPen& onP,
    
    14 14
                                          const QPen& offP,
    
    15
    -                                     FT_Outline* outln)
    
    15
    +                                     FT_Glyph glyph)
    
    16 16
     : onPen_(onP),
    
    17
    -  offPen_(offP),
    
    18
    -  outline_(outln)
    
    17
    +  offPen_(offP)
    
    19 18
     {
    
    19
    +  if (glyph->format != FT_GLYPH_FORMAT_OUTLINE)
    
    20
    +  {
    
    21
    +    outline_ = NULL;
    
    22
    +    return;
    
    23
    +  }
    
    24
    +  outline_ = &reinterpret_cast<FT_OutlineGlyph>(glyph)->outline;
    
    25
    +
    
    20 26
       FT_BBox cbox;
    
    21 27
     
    
    22 28
       FT_Outline_Get_CBox(outline_, &cbox);
    
    ... ... @@ -41,6 +47,8 @@ GlyphPointNumbers::paint(QPainter* painter,
    41 47
                              const QStyleOptionGraphicsItem* option,
    
    42 48
                              QWidget*)
    
    43 49
     {
    
    50
    +  if (!outline_)
    
    51
    +    return;
    
    44 52
       const qreal lod = option->levelOfDetailFromTransform(
    
    45 53
                                   painter->worldTransform());
    
    46 54
     
    

  • src/ftinspect/rendering/glyphpointnumbers.hpp
    ... ... @@ -10,6 +10,7 @@
    10 10
     
    
    11 11
     #include <ft2build.h>
    
    12 12
     #include <freetype/freetype.h>
    
    13
    +#include <freetype/ftglyph.h>
    
    13 14
     #include <freetype/ftoutln.h>
    
    14 15
     
    
    15 16
     
    
    ... ... @@ -19,7 +20,7 @@ class GlyphPointNumbers
    19 20
     public:
    
    20 21
       GlyphPointNumbers(const QPen& onPen,
    
    21 22
                         const QPen& offPen,
    
    22
    -                    FT_Outline* outline);
    
    23
    +                    FT_Glyph glyph);
    
    23 24
       QRectF boundingRect() const override;
    
    24 25
       void paint(QPainter* painter,
    
    25 26
                  const QStyleOptionGraphicsItem* option,
    

  • src/ftinspect/rendering/glyphpoints.cpp
    ... ... @@ -11,11 +11,17 @@
    11 11
     
    
    12 12
     GlyphPoints::GlyphPoints(const QPen& onP,
    
    13 13
                              const QPen& offP,
    
    14
    -                         FT_Outline* outln)
    
    14
    +                         FT_Glyph glyph)
    
    15 15
     : onPen_(onP),
    
    16
    -  offPen_(offP),
    
    17
    -  outline_(outln)
    
    16
    +  offPen_(offP)
    
    18 17
     {
    
    18
    +  if (glyph->format != FT_GLYPH_FORMAT_OUTLINE)
    
    19
    +  {
    
    20
    +    outline_ = NULL;
    
    21
    +    return;
    
    22
    +  }
    
    23
    +  outline_ = &reinterpret_cast<FT_OutlineGlyph>(glyph)->outline;
    
    24
    +
    
    19 25
       FT_BBox cbox;
    
    20 26
     
    
    21 27
       qreal halfPenWidth = qMax(onPen_.widthF(), offPen_.widthF()) / 2;
    
    ... ... @@ -41,6 +47,9 @@ GlyphPoints::paint(QPainter* painter,
    41 47
                        const QStyleOptionGraphicsItem* option,
    
    42 48
                        QWidget*)
    
    43 49
     {
    
    50
    +  if (!outline_)
    
    51
    +    return;
    
    52
    +
    
    44 53
       const qreal lod = option->levelOfDetailFromTransform(
    
    45 54
                                   painter->worldTransform());
    
    46 55
     
    

  • src/ftinspect/rendering/glyphpoints.hpp
    ... ... @@ -10,6 +10,7 @@
    10 10
     
    
    11 11
     #include <ft2build.h>
    
    12 12
     #include <freetype/freetype.h>
    
    13
    +#include <freetype/ftglyph.h>
    
    13 14
     #include <freetype/ftoutln.h>
    
    14 15
     
    
    15 16
     
    
    ... ... @@ -19,7 +20,7 @@ class GlyphPoints
    19 20
     public:
    
    20 21
       GlyphPoints(const QPen& onPen,
    
    21 22
                   const QPen& offPen,
    
    22
    -              FT_Outline* outline);
    
    23
    +              FT_Glyph glyph);
    
    23 24
       QRectF boundingRect() const override;
    
    24 25
       void paint(QPainter* painter,
    
    25 26
                  const QStyleOptionGraphicsItem* option,
    

  • src/ftinspect/rendering/renderutils.cpp
    ... ... @@ -28,6 +28,19 @@ cloneGlyph(FT_Glyph src)
    28 28
     void
    
    29 29
     transformOutlineToOrigin(FT_Outline* outline,
    
    30 30
                              FT_BBox* outControlBox)
    
    31
    +{
    
    32
    +  FT_Pos x, y;
    
    33
    +  computeTransformationToOrigin(outline,
    
    34
    +                                &x, &y,
    
    35
    +                                outControlBox);
    
    36
    +  FT_Outline_Translate(outline, x, y);
    
    37
    +}
    
    38
    +
    
    39
    +
    
    40
    +void computeTransformationToOrigin(FT_Outline* outline,
    
    41
    +                                   FT_Pos* outXOffset,
    
    42
    +                                   FT_Pos* outYOffset,
    
    43
    +                                   FT_BBox* outControlBox)
    
    31 44
     {
    
    32 45
       FT_BBox cbox;
    
    33 46
       FT_Outline_Get_CBox(outline, &cbox);
    
    ... ... @@ -37,8 +50,10 @@ transformOutlineToOrigin(FT_Outline* outline,
    37 50
       cbox.xMax = (cbox.xMax + 63) & ~63;
    
    38 51
       cbox.yMax = (cbox.yMax + 63) & ~63;
    
    39 52
       // we shift the outline to the origin for rendering later on
    
    40
    -  FT_Outline_Translate(outline, -cbox.xMin, -cbox.yMin);
    
    41
    -
    
    53
    +  if (outXOffset)
    
    54
    +    *outXOffset = -cbox.xMin;
    
    55
    +  if (outYOffset)
    
    56
    +    *outYOffset = -cbox.yMin;
    
    42 57
       if (outControlBox)
    
    43 58
         *outControlBox = cbox;
    
    44 59
     }
    

  • src/ftinspect/rendering/renderutils.hpp
    ... ... @@ -14,5 +14,10 @@ FT_Glyph cloneGlyph(FT_Glyph src);
    14 14
     void transformOutlineToOrigin(FT_Outline* outline,
    
    15 15
                                   FT_BBox* outControlBox);
    
    16 16
     
    
    17
    +void computeTransformationToOrigin(FT_Outline* outline,
    
    18
    +                                   FT_Pos* outXOffset,
    
    19
    +                                   FT_Pos* outYOffset,
    
    20
    +                                   FT_BBox* outControlBox);
    
    21
    +
    
    17 22
     
    
    18 23
     // end of renderutils.hpp


  • reply via email to

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