freetype-commit
[Top][All Lists]
Advanced

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

[freetype2-demos] master b76a242 4/4: [ftinspect] Display glyph point nu


From: Werner LEMBERG
Subject: [freetype2-demos] master b76a242 4/4: [ftinspect] Display glyph point numbers.
Date: Tue, 10 May 2016 03:20:41 +0000 (UTC)

branch: master
commit b76a242169fc72370434bf6e533312a473273cf5
Author: Werner Lemberg <address@hidden>
Commit: Werner Lemberg <address@hidden>

    [ftinspect] Display glyph point numbers.
    
    * src/ftinspect.cpp (GlyphPointNumbers::GlyphPointNumbers,
    GlyphPointNumbers::boundRect, GlyphPointNumbers::paint): New methods
    for constructing the set of glyph point numbers.
    (MainGUI::drawGlyph): Honor `glyph point indices' check box.
    (MainGUI::createLayout): Updated.
    (MainGUI::createConnections): Handle `showPointIndicesCheckBox'.
    
    * src/ftinspect.h (GlyphPoints): New class, derived from
    `QGraphicsItem'.
    (MainGUI): Mew member `currentGlyphPointNumbersItem'.
    Updated.
---
 ChangeLog         |   16 +++++
 src/ftinspect.cpp |  206 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 src/ftinspect.h   |   28 +++++++-
 3 files changed, 247 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index f413870..b8af160 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,19 @@
+2016-05-10  Werner Lemberg  <address@hidden>
+
+       [ftinspect] Display glyph point numbers.
+
+       * src/ftinspect.cpp (GlyphPointNumbers::GlyphPointNumbers,
+       GlyphPointNumbers::boundRect, GlyphPointNumbers::paint): New methods
+       for constructing the set of glyph point numbers.
+       (MainGUI::drawGlyph): Honor `glyph point indices' check box.
+       (MainGUI::createLayout): Updated.
+       (MainGUI::createConnections): Handle `showPointIndicesCheckBox'.
+
+       * src/ftinspect.h (GlyphPoints): New class, derived from
+       `QGraphicsItem'.
+       (MainGUI): Mew member `currentGlyphPointNumbersItem'.
+       Updated.
+
 2016-05-09  Werner Lemberg  <address@hidden>
 
        [ftinspect] Display glyph points.
diff --git a/src/ftinspect.cpp b/src/ftinspect.cpp
index b47dd9e..8e2853d 100644
--- a/src/ftinspect.cpp
+++ b/src/ftinspect.cpp
@@ -743,6 +743,193 @@ GlyphPoints::paint(QPainter* painter,
 }
 
 
+GlyphPointNumbers::GlyphPointNumbers(const QPen& onP,
+                                     const QPen& offP,
+                                     FT_Outline* outln)
+: onPen(onP),
+  offPen(offP),
+  outline(outln)
+{
+  FT_BBox cbox;
+
+  FT_Outline_Get_CBox(outline, &cbox);
+
+  // XXX fix bRect size
+  bRect.setCoords(qreal(cbox.xMin) / 64,
+                  -qreal(cbox.yMax) / 64,
+                  qreal(cbox.xMax) / 64,
+                  -qreal(cbox.yMin) / 64);
+}
+
+
+QRectF
+GlyphPointNumbers::boundingRect() const
+{
+  return bRect;
+}
+
+
+void
+GlyphPointNumbers::paint(QPainter* painter,
+                         const QStyleOptionGraphicsItem* option,
+                         QWidget*)
+{
+  const qreal lod = option->levelOfDetailFromTransform(
+                              painter->worldTransform());
+
+  // don't draw point numbers if magnification is too small
+  if (lod >= 10)
+  {
+    QFont font = painter->font();
+
+    // the following doesn't work correctly with scaling;
+    // it seems that Qt doesn't allow arbitrarily small font sizes
+    // that get magnified later on
+#if 0
+    // we want the same text size regardless of the scaling
+    font.setPointSizeF(font.pointSizeF() / lod);
+    painter->setFont(font);
+#else
+    font.setPointSizeF(font.pointSizeF() * 3 / 4);
+    painter->setFont(font);
+
+    QBrush onBrush(onPen.color());
+    QBrush offBrush(offPen.color());
+
+    painter->scale(1 / lod, 1 / lod);
+#endif
+
+    FT_Vector* points = outline->points;
+    FT_Short* contours = outline->contours;
+    char* tags = outline->tags;
+
+    QVector2D octants[8] = { QVector2D(1, 0),
+                             QVector2D(0.707, -0.707),
+                             QVector2D(0, -1),
+                             QVector2D(-0.707, -0.707),
+                             QVector2D(-1, 0),
+                             QVector2D(-0.707, 0.707),
+                             QVector2D(0, 1),
+                             QVector2D(0.707, 0.707) };
+
+
+    int ptIdx = 0;
+    for (int contIdx = 0; contIdx < outline->n_contours; contIdx++ )
+    {
+      for (;;)
+      {
+        short prevIdx, nextIdx;
+
+        // find previous and next point in outline
+        if (contIdx == 0)
+        {
+          if (contours[contIdx] == 0)
+          {
+            prevIdx = 0;
+            nextIdx = 0;
+          }
+          else
+          {
+            prevIdx = ptIdx > 0 ? ptIdx - 1
+                                : contours[contIdx];
+            nextIdx = ptIdx < contours[contIdx] ? ptIdx + 1
+                                                : 0;
+          }
+        }
+        else
+        {
+          prevIdx = ptIdx > (contours[contIdx - 1] + 1) ? ptIdx - 1
+                                                        : contours[contIdx];
+          nextIdx = ptIdx < contours[contIdx] ? ptIdx + 1
+                                              : contours[contIdx - 1] + 1;
+        }
+
+        // get vectors to previous and next point and normalize them;
+        QVector2D in(qreal(points[prevIdx].x - points[ptIdx].x) / 64,
+                     -qreal(points[prevIdx].y - points[ptIdx].y) / 64);
+        QVector2D out(qreal(points[nextIdx].x - points[ptIdx].x) / 64,
+                      -qreal(points[nextIdx].y - points[ptIdx].y) / 64);
+
+        in = in.normalized();
+        out = out.normalized();
+
+        QVector2D middle = in + out;
+        // check whether vector is very small, using a threshold of 1/8px
+        if (qAbs(middle.x()) < 1.0 / 8
+            && qAbs(middle.y()) < 1.0 / 8)
+        {
+          // in case of vectors in almost exactly opposite directions,
+          // use a vector orthogonal to them
+          middle.setX(out.y());
+          middle.setY(-out.x());
+
+          if (qAbs(middle.x()) < 1.0 / 8
+              && qAbs(middle.y()) < 1.0 / 8)
+          {
+            // use direction based on point index for the offset
+            // if we still don't have a good value
+            middle = octants[ptIdx % 8];
+          }
+        }
+
+        // normalize `middle' vector (which is never zero),
+        // then multiply by 8 to get some distance between
+        // the point and the number
+        middle = middle.normalized() * 8;
+
+        // we now position the point number in the opposite
+        // direction of the `middle' vector,
+        QString number = QString::number(ptIdx);
+
+#if 0
+        // this fails, see comment above
+        int size = 10000;
+        qreal x = qreal(points[ptIdx].x) / 64 - middle.x() / lod;
+        qreal y = -qreal(points[ptIdx].y) / 64 - middle.y() / lod;
+        QPointF corner(x, y);
+        int flags = middle.x() > 0 ? Qt::AlignRight
+                                   : Qt::AlignLeft;
+        if (flags == Qt::AlignRight)
+          corner.rx() -= size;
+        QRectF posRect(corner, QSizeF(size, size));
+
+        if (tags[ptIdx] & FT_CURVE_TAG_ON)
+          painter->setPen(onPen);
+        else
+          painter->setPen(offPen);
+
+        painter->drawText(posRect, flags, number);
+#else
+        // convert text string to a path object
+        QPainterPath path;
+        path.addText(QPointF(0, 0), font, number);
+        QRectF ctrlPtRect = path.controlPointRect();
+
+        qreal x = qreal(points[ptIdx].x) / 64 * lod - middle.x();
+        qreal y = -qreal(points[ptIdx].y) / 64 * lod - middle.y();
+
+        qreal heuristicOffset = 2;
+        if (middle.x() > 0)
+          path.translate(x - ctrlPtRect.width() - heuristicOffset,
+                         y + ctrlPtRect.height() / 2);
+        else
+          path.translate(x,
+                         y + ctrlPtRect.height() / 2);
+
+        painter->fillPath(path,
+                          tags[ptIdx] & FT_CURVE_TAG_ON ? onBrush
+                                                        : offBrush);
+#endif
+
+        ptIdx++;
+        if (ptIdx > contours[contIdx])
+          break;
+      }
+    }
+  }
+}
+
+
 MainGUI::MainGUI()
 {
   engine = NULL;
@@ -1344,6 +1531,14 @@ MainGUI::drawGlyph()
     currentGlyphPointsItem = NULL;
   }
 
+  if (currentGlyphPointNumbersItem)
+  {
+    glyphScene->removeItem(currentGlyphPointNumbersItem);
+    delete currentGlyphPointNumbersItem;
+
+    currentGlyphPointNumbersItem = NULL;
+  }
+
   if (currentFontIndex >= 0
       && currentFaceIndex >= 0)
   {
@@ -1360,6 +1555,14 @@ MainGUI::drawGlyph()
       {
         currentGlyphPointsItem = new GlyphPoints(onPen, offPen, outline);
         glyphScene->addItem(currentGlyphPointsItem);
+
+        if (showPointIndicesCheckBox->isChecked())
+        {
+          currentGlyphPointNumbersItem = new GlyphPointNumbers(onPen,
+                                                               offPen,
+                                                               outline);
+          glyphScene->addItem(currentGlyphPointNumbersItem);
+        }
       }
     }
   }
@@ -1559,6 +1762,7 @@ MainGUI::createLayout()
 
   currentGlyphOutlineItem = NULL;
   currentGlyphPointsItem = NULL;
+  currentGlyphPointNumbersItem = NULL;
   drawGlyph();
 
   glyphView = new QGraphicsView;
@@ -1696,6 +1900,8 @@ MainGUI::createConnections()
           SLOT(checkAutoHinting()));
   connect(showPointsCheckBox, SIGNAL(clicked()),
           SLOT(checkShowPoints()));
+  connect(showPointIndicesCheckBox, SIGNAL(clicked()),
+          SLOT(drawGlyph()));
   connect(showOutlinesCheckBox, SIGNAL(clicked()),
           SLOT(drawGlyph()));
 
diff --git a/src/ftinspect.h b/src/ftinspect.h
index c0034b6..1cadbe6 100644
--- a/src/ftinspect.h
+++ b/src/ftinspect.h
@@ -49,6 +49,7 @@
 #include <QTabWidget>
 #include <QTransform>
 #include <QVariant>
+#include <QVector2D>
 #include <QVBoxLayout>
 #include <QWidget>
 
@@ -208,6 +209,26 @@ private:
 };
 
 
+class GlyphPointNumbers
+: public QGraphicsItem
+{
+public:
+  GlyphPointNumbers(const QPen&,
+                    const QPen&,
+                    FT_Outline*);
+  QRectF boundingRect() const;
+  void paint(QPainter*,
+             const QStyleOptionGraphicsItem*,
+             QWidget*);
+
+private:
+  QPen onPen;
+  QPen offPen;
+  FT_Outline* outline;
+  QRectF bRect;
+};
+
+
 // we want to grey out items in a combo box;
 // since Qt doesn't provide a function for this we derive a class
 class QComboBoxx
@@ -292,6 +313,10 @@ private:
   QHash<FaceID, int> faceIDHash;
 
   // layout related stuff
+  GlyphOutline *currentGlyphOutlineItem;
+  GlyphPoints *currentGlyphPointsItem;
+  GlyphPointNumbers *currentGlyphPointNumbersItem;
+
   QAction *aboutAct;
   QAction *aboutQtAct;
   QAction *closeFontAct;
@@ -317,9 +342,6 @@ private:
 
   QDoubleSpinBox *sizeDoubleSpinBox;
 
-  QGraphicsItem *currentGlyphOutlineItem;
-  QGraphicsItem *currentGlyphPointsItem;
-
   QGraphicsScene *glyphScene;
   QGraphicsView *glyphView;
 



reply via email to

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