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-3] [ftinspect] Add cach


From: Charlie Jiang (@cqjjjzr)
Subject: [Git][freetype/freetype-demos][gsoc-2022-chariri-3] [ftinspect] Add caching of `QImage` and dimension info in Continuous View.
Date: Wed, 27 Jul 2022 10:33:01 +0000

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

Commits:

  • 794b613d
    by Charlie Jiang at 2022-07-27T18:32:42+08:00
    [ftinspect] Add caching of `QImage` and dimension info in Continuous View.
    
    This gives further possibility of implementation click-for-detail and
    dragging features.
    Also improves performance, but very slightly because the cache is purged
    aggresively.
    
    * src/ftinspect/rendering/glyphcontinuous.cpp,
      src/ftinspect/rendering/glyphcontinuous.hpp:
      Implementation the caching, remove non-cached drawing of the glyphs.
    
    * src/ftinspect/engine/stringrenderer.cpp,
      src/ftinspect/engine/stringrenderer.hpp:
      Add an argument to pass the current `GlyphContext` to both callbacks.
    
    * src/ftinspect/panels/continuous.cpp: Purge caches at proper time.
    

5 changed files:

Changes:

  • src/ftinspect/engine/stringrenderer.cpp
    ... ... @@ -510,7 +510,7 @@ StringRenderer::renderLine(int x,
    510 510
         {
    
    511 511
           rect.setX(rect.x() + (pen.x >> 6));
    
    512 512
           rect.setY(height - rect.y() - (pen.y >> 6));
    
    513
    -      renderImageCallback_(colorLayerImage, rect);
    
    513
    +      renderImageCallback_(colorLayerImage, rect, ctx);
    
    514 514
         }
    
    515 515
         else
    
    516 516
         {
    
    ... ... @@ -569,7 +569,7 @@ StringRenderer::renderLine(int x,
    569 569
               && bbox.yMin <= height)
    
    570 570
           {
    
    571 571
             FT_Vector penPos = { (pen.x >> 6), height - (pen.y >> 6) };
    
    572
    -        renderCallback_(image, penPos);
    
    572
    +        renderCallback_(image, penPos, ctx);
    
    573 573
           }
    
    574 574
     
    
    575 575
           FT_Done_Glyph(image);
    

  • src/ftinspect/engine/stringrenderer.hpp
    ... ... @@ -61,13 +61,17 @@ public:
    61 61
        * contains no points, and thus can't be translated to the desired pen
    
    62 62
        * position.
    
    63 63
        */
    
    64
    -  using RenderCallback = std::function<void(FT_Glyph, FT_Vector)>;
    
    64
    +  using RenderCallback = std::function<void(FT_Glyph, 
    
    65
    +                                            FT_Vector, 
    
    66
    +                                            GlyphContext&)>;
    
    65 67
       /*
    
    66 68
        * For color layered fonts, this will direct render the QImage for you.
    
    67 69
        * TODO: Remove `RenderCallback` and do QImage creation in this class?
    
    68 70
        * The receiver is responsible for deleteing the QImage.
    
    69 71
        */
    
    70
    -  using RenderImageCallback = std::function<void(QImage*, QRect)>;
    
    72
    +  using RenderImageCallback = std::function<void(QImage*, 
    
    73
    +                                                 QRect, 
    
    74
    +                                                 GlyphContext&)>;
    
    71 75
       /*
    
    72 76
        * The glyph pointer may be replaced. In that case, ownership is transfered
    
    73 77
        * to the renderer, and the new glyph will be eventually freed by
    

  • src/ftinspect/panels/continuous.cpp
    ... ... @@ -30,6 +30,7 @@ ContinuousTab::repaintGlyph()
    30 30
       sizeSelector_->applyToEngine(engine_);
    
    31 31
       
    
    32 32
       syncSettings();
    
    33
    +  canvas_->purgeCache();
    
    33 34
       canvas_->repaint();
    
    34 35
     }
    
    35 36
     
    
    ... ... @@ -41,6 +42,7 @@ ContinuousTab::reloadFont()
    41 42
       setGlyphCount(qBound(0, currentGlyphCount_, INT_MAX));
    
    42 43
       setCharMaps(engine_->currentFontCharMaps());
    
    43 44
       canvas_->stringRenderer().reloadAll();
    
    45
    +  canvas_->purgeCache();
    
    44 46
       repaintGlyph();
    
    45 47
     }
    
    46 48
     
    

  • src/ftinspect/rendering/glyphcontinuous.cpp
    ... ... @@ -12,6 +12,37 @@
    12 12
     #include <freetype/ftbitmap.h>
    
    13 13
     
    
    14 14
     
    
    15
    +GlyphCacheEntry::~GlyphCacheEntry()
    
    16
    +{
    
    17
    +  delete image;
    
    18
    +}
    
    19
    +
    
    20
    +
    
    21
    +GlyphCacheEntry::GlyphCacheEntry(GlyphCacheEntry&& other) noexcept
    
    22
    +{
    
    23
    +  *this = std::move(other);
    
    24
    +}
    
    25
    +
    
    26
    +
    
    27
    +GlyphCacheEntry&
    
    28
    +GlyphCacheEntry::operator=(GlyphCacheEntry&& other) noexcept
    
    29
    +{
    
    30
    +  if (this == &other)
    
    31
    +    return *this;
    
    32
    +
    
    33
    +  auto oldImage = image;
    
    34
    +  image = other.image;
    
    35
    +  basePosition = other.basePosition;
    
    36
    +  penPos = other.penPos;
    
    37
    +  charCode = other.charCode;
    
    38
    +  glyphIndex = other.glyphIndex;
    
    39
    +  advance = other.advance;
    
    40
    +  hasAdvance = other.hasAdvance;
    
    41
    +  other.image = oldImage;
    
    42
    +  return *this;
    
    43
    +}
    
    44
    +
    
    45
    +
    
    15 46
     GlyphContinuous::GlyphContinuous(QWidget* parent, Engine* engine)
    
    16 47
     : QWidget(parent),
    
    17 48
       engine_(engine),
    
    ... ... @@ -38,9 +69,11 @@ GlyphContinuous::setSource(Source source)
    38 69
       {
    
    39 70
       case SRC_AllGlyphs:
    
    40 71
         stringRenderer_.setUseAllGlyphs();
    
    72
    +    positionDelta_ = {};
    
    41 73
         break;
    
    42 74
     
    
    43 75
       case SRC_TextStringRepeated:
    
    76
    +    positionDelta_ = {};
    
    44 77
       case SRC_TextString:
    
    45 78
         updateRendererText();
    
    46 79
         break;
    
    ... ... @@ -56,6 +89,14 @@ GlyphContinuous::setSourceText(QString text)
    56 89
     }
    
    57 90
     
    
    58 91
     
    
    92
    +void
    
    93
    +GlyphContinuous::purgeCache()
    
    94
    +{
    
    95
    +  glyphCache_.clear();
    
    96
    +  currentWritingLine_ = NULL;
    
    97
    +}
    
    98
    +
    
    99
    +
    
    59 100
     void
    
    60 101
     GlyphContinuous::paintEvent(QPaintEvent* event)
    
    61 102
     {
    
    ... ... @@ -63,10 +104,9 @@ GlyphContinuous::paintEvent(QPaintEvent* event)
    63 104
       painter.begin(this);
    
    64 105
       painter.fillRect(rect(), Qt::white);
    
    65 106
     
    
    66
    -  prePaint();
    
    67
    -
    
    68
    -  paintByRenderer(&painter);
    
    69
    -  emit displayingCountUpdated(displayingCount_);
    
    107
    +  if (glyphCache_.empty())
    
    108
    +    fillCache();
    
    109
    +  paintCache(&painter);
    
    70 110
     
    
    71 111
       painter.end();
    
    72 112
     }
    
    ... ... @@ -84,27 +124,28 @@ GlyphContinuous::wheelEvent(QWheelEvent* event)
    84 124
     
    
    85 125
     
    
    86 126
     void
    
    87
    -GlyphContinuous::paintByRenderer(QPainter* painter)
    
    127
    +GlyphContinuous::resizeEvent(QResizeEvent* event)
    
    88 128
     {
    
    89
    -  if (mode_ == M_Stroked)
    
    90
    -  {
    
    91
    -    auto radius = static_cast<FT_Fixed>(metrics_.y_ppem * 64 * strokeRadius_);
    
    92
    -    FT_Stroker_Set(stroker_, radius,
    
    93
    -                   FT_STROKER_LINECAP_ROUND,
    
    94
    -                   FT_STROKER_LINEJOIN_ROUND,
    
    95
    -                   0);
    
    96
    -  }
    
    129
    +  purgeCache();
    
    130
    +  QWidget::resizeEvent(event);
    
    131
    +}
    
    132
    +
    
    133
    +
    
    134
    +void
    
    135
    +GlyphContinuous::paintByRenderer()
    
    136
    +{
    
    137
    +  purgeCache();
    
    97 138
     
    
    98 139
       stringRenderer_.setRepeated(source_ == SRC_TextStringRepeated);
    
    99 140
       stringRenderer_.setCallback(
    
    100
    -    [&](FT_Glyph glyph, FT_Vector penPos)
    
    141
    +    [&](FT_Glyph glyph, FT_Vector penPos, GlyphContext& ctx)
    
    101 142
         {
    
    102
    -      drawSingleGlyph(painter, glyph, penPos);
    
    143
    +      saveSingleGlyph(glyph, penPos, ctx);
    
    103 144
         });
    
    104 145
       stringRenderer_.setImageCallback(
    
    105
    -    [&](QImage* image, QRect pos)
    
    146
    +    [&](QImage* image, QRect pos, GlyphContext& ctx)
    
    106 147
         {
    
    107
    -      drawSingleGlyphImage(painter, image, pos);
    
    148
    +      saveSingleGlyphImage(image, pos, ctx);
    
    108 149
         });
    
    109 150
       stringRenderer_.setPreprocessCallback(
    
    110 151
         [&](FT_Glyph* ptr)
    
    ... ... @@ -114,7 +155,7 @@ GlyphContinuous::paintByRenderer(QPainter* painter)
    114 155
       stringRenderer_.setLineBeginCallback(
    
    115 156
         [&](FT_Vector pos, double size)
    
    116 157
         {
    
    117
    -      beginLine(painter, pos, size);
    
    158
    +      beginSaveLine(pos, size);
    
    118 159
         });
    
    119 160
       displayingCount_ = stringRenderer_.render(width(), height(), beginIndex_);
    
    120 161
     }
    
    ... ... @@ -168,6 +209,31 @@ GlyphContinuous::transformGlyphStroked(FT_Glyph glyph)
    168 209
     }
    
    169 210
     
    
    170 211
     
    
    212
    +void
    
    213
    +GlyphContinuous::paintCache(QPainter* painter)
    
    214
    +{
    
    215
    +  if (stringRenderer_.isWaterfall())
    
    216
    +    positionDelta_.setY(0);
    
    217
    +  for (auto& line : glyphCache_)
    
    218
    +  {
    
    219
    +    beginDrawCacheLine(painter, line);
    
    220
    +    for (auto& glyph : line.entries)
    
    221
    +    {
    
    222
    +      drawCacheGlyph(painter, glyph);
    
    223
    +    }
    
    224
    +  }
    
    225
    +}
    
    226
    +
    
    227
    +
    
    228
    +void
    
    229
    +GlyphContinuous::fillCache()
    
    230
    +{
    
    231
    +  prePaint();
    
    232
    +  paintByRenderer();
    
    233
    +  emit displayingCountUpdated(displayingCount_);
    
    234
    +}
    
    235
    +
    
    236
    +
    
    171 237
     void
    
    172 238
     GlyphContinuous::prePaint()
    
    173 239
     {
    
    ... ... @@ -204,6 +270,15 @@ GlyphContinuous::prePaint()
    204 270
     
    
    205 271
       emboldeningX_ = (FT_Pos)(metrics_.y_ppem * 64 * boldX_);
    
    206 272
       emboldeningY_ = (FT_Pos)(metrics_.y_ppem * 64 * boldY_);
    
    273
    +
    
    274
    +  if (mode_ == M_Stroked)
    
    275
    +  {
    
    276
    +    auto radius = static_cast<FT_Fixed>(metrics_.y_ppem * 64 * strokeRadius_);
    
    277
    +    FT_Stroker_Set(stroker_, radius,
    
    278
    +                   FT_STROKER_LINECAP_ROUND,
    
    279
    +                   FT_STROKER_LINEJOIN_ROUND,
    
    280
    +                   0);
    
    281
    +  }
    
    207 282
     }
    
    208 283
     
    
    209 284
     
    
    ... ... @@ -240,9 +315,65 @@ GlyphContinuous::preprocessGlyph(FT_Glyph* glyphPtr)
    240 315
     
    
    241 316
     
    
    242 317
     void
    
    243
    -GlyphContinuous::beginLine(QPainter* painter,
    
    244
    -                           FT_Vector pos,
    
    245
    -                           double sizePoint)
    
    318
    +GlyphContinuous::beginSaveLine(FT_Vector pos,
    
    319
    +                               double sizePoint)
    
    320
    +{
    
    321
    +  glyphCache_.emplace_back();
    
    322
    +  currentWritingLine_ = &glyphCache_.back();
    
    323
    +  currentWritingLine_->sizePoint = sizePoint;
    
    324
    +  currentWritingLine_->basePosition = { static_cast<int>(pos.x),
    
    325
    +                                        static_cast<int>(pos.y) };
    
    326
    +}
    
    327
    +
    
    328
    +
    
    329
    +void
    
    330
    +GlyphContinuous::saveSingleGlyph(FT_Glyph glyph,
    
    331
    +                                 FT_Vector penPos,
    
    332
    +                                 GlyphContext gctx)
    
    333
    +{
    
    334
    +  if (!currentWritingLine_)
    
    335
    +    return;
    
    336
    +
    
    337
    +  currentWritingLine_->entries.push_back(std::move(GlyphCacheEntry{}));
    
    338
    +  auto& entry = currentWritingLine_->entries.back();
    
    339
    +
    
    340
    +  QRect rect;
    
    341
    +  QImage* image = engine_->convertGlyphToQImage(glyph, &rect, false);
    
    342
    +  rect.setTop(height() - rect.top()); // TODO Don't place this here...
    
    343
    +
    
    344
    +  entry.image = image;
    
    345
    +  entry.basePosition = rect;
    
    346
    +  entry.charCode = gctx.charCode;
    
    347
    +  entry.glyphIndex = gctx.glyphIndex;
    
    348
    +  entry.advance = glyph->advance;
    
    349
    +  entry.penPos = { penPos.x, penPos.y };
    
    350
    +
    
    351
    +  // todo more info
    
    352
    +}
    
    353
    +
    
    354
    +
    
    355
    +void
    
    356
    +GlyphContinuous::saveSingleGlyphImage(QImage* image,
    
    357
    +                                      QRect pos,
    
    358
    +                                      GlyphContext gctx)
    
    359
    +{
    
    360
    +  if (!currentWritingLine_)
    
    361
    +    return;
    
    362
    +
    
    363
    +  currentWritingLine_->entries.push_back(std::move(GlyphCacheEntry{}));
    
    364
    +  auto& entry = currentWritingLine_->entries.back();
    
    365
    +
    
    366
    +  entry.image = image;
    
    367
    +  entry.basePosition = pos;
    
    368
    +  entry.charCode = gctx.charCode;
    
    369
    +  entry.glyphIndex = gctx.glyphIndex;
    
    370
    +  entry.hasAdvance = false;
    
    371
    +}
    
    372
    +
    
    373
    +
    
    374
    +void
    
    375
    +GlyphContinuous::beginDrawCacheLine(QPainter* painter,
    
    376
    +                                    const GlyphCacheLine& line)
    
    246 377
     {
    
    247 378
       // Now only used by waterfall mode to draw a size indicator.
    
    248 379
       if (!stringRenderer_.isWaterfall())
    
    ... ... @@ -252,54 +383,38 @@ GlyphContinuous::beginLine(QPainter* painter,
    252 383
       }
    
    253 384
     
    
    254 385
       auto oldFont = painter->font();
    
    255
    -  oldFont.setPointSizeF(sizePoint);
    
    386
    +  oldFont.setPointSizeF(line.sizePoint);
    
    256 387
       painter->setFont(oldFont);
    
    257 388
       auto metrics = painter->fontMetrics();
    
    258 389
     
    
    259
    -  auto sizePrefix = QString("%1: ").arg(sizePoint);
    
    260
    -  QPoint posQ = { static_cast<int>(pos.x),
    
    261
    -                  static_cast<int>(pos.y) };
    
    262
    -  painter->drawText(posQ, sizePrefix);
    
    390
    +  auto sizePrefix = QString("%1: ").arg(line.sizePoint);
    
    391
    +  painter->drawText(line.basePosition, sizePrefix);
    
    263 392
     
    
    264 393
       sizeIndicatorOffset_ = metrics.horizontalAdvance(sizePrefix);
    
    265 394
     }
    
    266 395
     
    
    267 396
     
    
    268 397
     void
    
    269
    -GlyphContinuous::drawSingleGlyph(QPainter* painter, 
    
    270
    -                                 FT_Glyph glyph,
    
    271
    -                                 FT_Vector penPos)
    
    398
    +GlyphContinuous::drawCacheGlyph(QPainter* painter,
    
    399
    +                                const GlyphCacheEntry& entry)
    
    272 400
     {
    
    273 401
       // ftview.c:557
    
    274
    -  int width = glyph->advance.x ? glyph->advance.x >> 16
    
    275
    -                               : metrics_.y_ppem / 2;
    
    402
    +  // Well, metrics is also part of the cache...
    
    403
    +  int width = entry.advance.x ? entry.advance.x >> 16
    
    404
    +                              : metrics_.y_ppem / 2;
    
    276 405
     
    
    277
    -  if (glyph->advance.x == 0 && !stringRenderer_.isWaterfall())
    
    406
    +  if (entry.advance.x == 0 && !stringRenderer_.isWaterfall())
    
    278 407
       {
    
    279 408
         // Draw a red square to indicate
    
    280
    -    painter->fillRect(penPos.x, penPos.y - width, width, width, Qt::red);
    
    409
    +    auto squarePoint = entry.penPos;
    
    410
    +    squarePoint.setY(squarePoint.y() - width);
    
    411
    +    painter->fillRect(QRect(squarePoint, QSize(width, width)), Qt::red);
    
    281 412
       }
    
    282 413
     
    
    283
    -  QRect rect;
    
    284
    -  QImage* image = engine_->convertGlyphToQImage(glyph, &rect, false);
    
    285
    -  rect.setTop(height() - rect.top()); // TODO Don't place this here...
    
    414
    +  QRect rect = entry.basePosition;
    
    286 415
       rect.setLeft(rect.left() + sizeIndicatorOffset_);
    
    287 416
     
    
    288
    -  painter->drawImage(rect.topLeft(), *image);
    
    289
    -  delete image;
    
    290
    -}
    
    291
    -
    
    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;
    
    417
    +  painter->drawImage(rect.topLeft(), *entry.image);
    
    303 418
     }
    
    304 419
     
    
    305 420
     
    

  • src/ftinspect/rendering/glyphcontinuous.hpp
    ... ... @@ -8,8 +8,10 @@
    8 8
     #include "../engine/stringrenderer.hpp"
    
    9 9
     
    
    10 10
     #include <utility>
    
    11
    +#include <vector>
    
    11 12
     
    
    12 13
     #include <QWidget>
    
    14
    +#include <QImage>
    
    13 15
     
    
    14 16
     #include <freetype/freetype.h>
    
    15 17
     #include <freetype/ftglyph.h>
    
    ... ... @@ -17,6 +19,34 @@
    17 19
     #include <freetype/ftstroke.h>
    
    18 20
     
    
    19 21
     
    
    22
    +struct GlyphCacheEntry
    
    23
    +{
    
    24
    +  QImage* image = NULL;
    
    25
    +  QRect basePosition = {};
    
    26
    +  QPoint penPos = {};
    
    27
    +  int charCode = -1;
    
    28
    +  int glyphIndex = -1;
    
    29
    +
    
    30
    +  FT_Vector advance = {};
    
    31
    +  bool hasAdvance = false;
    
    32
    +
    
    33
    +  GlyphCacheEntry() {}
    
    34
    +  ~GlyphCacheEntry();
    
    35
    +  GlyphCacheEntry(const GlyphCacheEntry& other) = delete;
    
    36
    +  GlyphCacheEntry& operator=(const GlyphCacheEntry& other) = delete;
    
    37
    +  GlyphCacheEntry(GlyphCacheEntry&& other) noexcept;
    
    38
    +  GlyphCacheEntry& operator=(GlyphCacheEntry&& other) noexcept;
    
    39
    +};
    
    40
    +
    
    41
    +
    
    42
    +struct GlyphCacheLine
    
    43
    +{
    
    44
    +  QPoint basePosition = {};
    
    45
    +  double sizePoint = 0.0;
    
    46
    +  std::vector<GlyphCacheEntry> entries;
    
    47
    +};
    
    48
    +
    
    49
    +
    
    20 50
     class Engine;
    
    21 51
     class GlyphContinuous
    
    22 52
     : public QWidget
    
    ... ... @@ -56,6 +86,8 @@ public:
    56 86
       void setStrokeRadius(double radius) { strokeRadius_ = radius; }
    
    57 87
       void setSourceText(QString text);
    
    58 88
     
    
    89
    +  void purgeCache();
    
    90
    +
    
    59 91
     signals:
    
    60 92
       void wheelNavigate(int steps);
    
    61 93
       void wheelResize(int steps);
    
    ... ... @@ -64,6 +96,7 @@ signals:
    64 96
     protected:
    
    65 97
       void paintEvent(QPaintEvent* event) override;
    
    66 98
       void wheelEvent(QWheelEvent* event) override;
    
    99
    +  void resizeEvent(QResizeEvent* event) override;
    
    67 100
     
    
    68 101
     private:
    
    69 102
       Engine* engine_;
    
    ... ... @@ -86,7 +119,12 @@ private:
    86 119
     
    
    87 120
       FT_Stroker stroker_;
    
    88 121
     
    
    89
    -  void paintByRenderer(QPainter* painter);
    
    122
    +  std::vector<GlyphCacheLine> glyphCache_;
    
    123
    +  GlyphCacheLine* currentWritingLine_ = NULL;
    
    124
    +
    
    125
    +  QPoint positionDelta_;
    
    126
    +
    
    127
    +  void paintByRenderer();
    
    90 128
     
    
    91 129
       // These two are used indendpent of current glyph variables
    
    92 130
       // and assumes ownership of glyphs, but don't free them.
    
    ... ... @@ -94,18 +132,23 @@ private:
    94 132
       void transformGlyphFancy(FT_Glyph glyph);
    
    95 133
       FT_Glyph transformGlyphStroked(FT_Glyph glyph);
    
    96 134
     
    
    135
    +  void paintCache(QPainter* painter);
    
    136
    +  void fillCache();
    
    97 137
       void prePaint();
    
    98 138
       void updateRendererText();
    
    99 139
       void preprocessGlyph(FT_Glyph* glyphPtr);
    
    100
    -  void beginLine(QPainter* painter,
    
    101
    -                 FT_Vector pos, 
    
    102
    -                 double sizePoint);
    
    103
    -  void drawSingleGlyph(QPainter* painter,
    
    104
    -                       FT_Glyph glyph,
    
    105
    -                       FT_Vector penPos);
    
    106
    -  void drawSingleGlyphImage(QPainter* painter,
    
    107
    -                            QImage* image,
    
    108
    -                            QRect pos);
    
    140
    +  void beginSaveLine(FT_Vector pos,
    
    141
    +                     double sizePoint);
    
    142
    +  void saveSingleGlyph(FT_Glyph glyph,
    
    143
    +                       FT_Vector penPos,
    
    144
    +                       GlyphContext gctx);
    
    145
    +  void saveSingleGlyphImage(QImage* image,
    
    146
    +                            QRect pos,
    
    147
    +                            GlyphContext gctx);
    
    148
    +  void beginDrawCacheLine(QPainter* painter,
    
    149
    +                          const GlyphCacheLine& line);
    
    150
    +  void drawCacheGlyph(QPainter* painter,
    
    151
    +                      const GlyphCacheEntry& entry);
    
    109 152
     };
    
    110 153
     
    
    111 154
     
    


  • reply via email to

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