ROOT logo
// $Id: TabletStrokeList.cxx 2437 2010-08-15 11:06:50Z matevz $

// Copyright (C) 1999-2008, Matevz Tadel. All rights reserved.
// This file is part of GLED, released under GNU General Public License version 2.
// For the licensing terms see $GLEDSYS/LICENSE or http://www.gnu.org/.

#include "TabletStrokeList.h"
#include "TabletStrokeList.c7"
#include "TabletStroke.h"

#include "Gled/XTReqCanvas.h"
#include "TH1.h"
#include "TH2.h"
#include "TCanvas.h"

// TabletStrokeList

//______________________________________________________________________________
//
// Potential is really (distance-from-point)^2
//
// mWidth         - radius where potential is one (for full-pressure)
// mPotentialExp  - exponent applied to this potential, usually negative
// mPressureAlpha - exponent of the pressure curve

ClassImp(TabletStrokeList);

//==============================================================================

void TabletStrokeList::_init()
{
  mAlgorithm      =  PA_CubicInterpolation;
  mWidth          =  0.01;
  mPotentialExp   = -0.5;
  mPressureAlpha  =  2;
  mMaxInterPoint  =  0.015;
  bMakeCubHistos  = false;

  mHCubTimevsTime = mHCubTimevsN = 0;
  mHN = mHCubTime20 = mHDeriv =  mHDeriv20 = 0;
}

TabletStrokeList::TabletStrokeList(const Text_t* n, const Text_t* t) :
  ZNode(n, t),
  mKDTree(0)
{
  _init();
}

TabletStrokeList::~TabletStrokeList()
{
  ClearKDStuff();
}

//==============================================================================

void TabletStrokeList::calculate_qubic_coeffs(const vSTabletPoint_t& vec, Int_t i,
					      CCoefs& c)
{
  const STabletPoint& pm = vec[i-1];
  const STabletPoint& p0 = vec[i];
  const STabletPoint& p1 = vec[i+1];
  const STabletPoint& pM = vec[i+2];

  const Float_t T  = p1.t - p0.t;
  const Float_t T2 = T * T;
  const Float_t T3 = T * T2;

  c.D = p0;
  c.C = (p1 - pm) / (p1.t - pm.t);

  const STabletPoint Q = p1 - T*c.C - c.D;
  const STabletPoint R = (pM - p0) / (pM.t - p0.t) - c.C;

  c.B = (T3*R - 3.0f*Q) / (T2*(2*T2 - 3.0f));
  c.A = (Q - T2*c.B) / T3;
}

void TabletStrokeList::MakeKDStuff()
{
  if (mKDTree)
    ClearKDStuff();

  Stepper<TabletStroke> stepper(this);
  {
    Int_t n_points = 0;
    while (stepper.step())
    {
      n_points += stepper->get_num_points();
    }
    mPointRefs.reserve(n_points);
    mArrX.reserve(n_points);
    mArrY.reserve(n_points);
    if (mAlgorithm == PA_CubicInterpolation)
      mCCoefs.reserve(n_points);
  }
  stepper.reset(this);

  while (stepper.step())
  {
    Int_t min, max;
    stepper->get_draw_range(min, max);
    for (Int_t i = min; i <= max; ++i)
    {
      STabletPoint &p = stepper->mPoints[i];
      mPointRefs.push_back(&p);
      mArrX.push_back(p.x);
      mArrY.push_back(p.y);

      if (mAlgorithm == PA_CubicInterpolation)
      {
	mCCoefs.push_back(CCoefs());
	if (i < max)
	  calculate_qubic_coeffs(stepper->mPoints, i, mCCoefs.back());
      }
    }
  }

  mKDTree = new TKDTreeIF(mArrX.size(), 2, 1);
  mKDTree->SetData(0, &mArrX[0]);
  mKDTree->SetData(1, &mArrY[0]);
  mKDTree->Build();  
}

void TabletStrokeList::ClearKDStuff()
{
  if (mKDTree)
  {
    delete mKDTree; mKDTree = 0;
    mPointRefs.clear();
    mArrX.clear();
    mArrY.clear();
    mCCoefs.clear();
  }
}

//==============================================================================

void TabletStrokeList::PrintClose(Float_t x, Float_t y, Float_t rad)
{
  if (mKDTree == 0)
    return;

  Float_t       point[2] = { x, y };
  vector<Int_t> res;

  mKDTree->FindInRange(point, rad, res);

  printf("TabletStrokeList::PrintClose npoints=%d, all stored=%d\n",
	 (Int_t) res.size(), (Int_t) mPointRefs.size());
}

//==============================================================================

void TabletStrokeList::GTSIsoBegin(GTSIsoMaker* /*maker*/, Double_t iso_value)
{
  if (mKDTree == 0 || (mAlgorithm == PA_CubicInterpolation && mCCoefs.empty()))
    MakeKDStuff();

  using namespace TMath;

  // Find distance where two consequitive points just make up the iso surface.
  // Standard maximum distance in tablet space is 0.01, default we take is 0.015.
  {
    const Double_t TR = mMaxInterPoint;
    const Double_t TE = 2.0*mPotentialExp;
    const Double_t C  = iso_value * Power(mWidth, TE);
    Double_t R = mWidth;
    Double_t V, D;
    Int_t N = 0;
    do
    {
      V = Power(R, TE) + Power(R + TR, TE) - C;
      D = TE * (Power(R, TE - 1) + Power(R + TR, TE - 1));
      // printf("Tangent method: R=%g, V=%g, D=%g\n", R, V, D);
      R -= V / D;
    } while (Abs(V) > 1e-8 && ++N < 100);

    mSearchRad = TR + R;
  }
  printf("TabletStrokeList::GTSIsoBegin iso=%f, search-radius=%f\n", iso_value, mSearchRad);

  if (bMakeCubHistos && mAlgorithm == PA_CubicInterpolation)
  {
    mHN             = new TH1I("N", "Number iterations", 21, -0.5, 20.5);
    mHCubTimevsTime = new TH2I("CubTimevsTime", "Tcub vs Tlin", 1000, -4, 5, 1000, -4, 5);
    mHCubTimevsN    = new TH2I("CubTimevsN", "Tcub vs N", 21, -0.5, 20.5, 1000, -4, 5);
    mHCubTime20     = new TH1I("CubTime20", "Tcub at N=20", 1000, -4, 5);
    mHDeriv         = new TH1I("Deriv", "Derivative value x 1e6", 1000, -1, 1);
    mHDeriv20       = new TH1I("Deriv20", "Derivative value x 1e3 at N=20", 1000, -1, 1);
  }
}

namespace
{
  Double_t sqr(Double_t x) { return x*x; }
}

void TabletStrokeList::distance_derivatives(Float_t t, const HPointF& P, const CCoefs& c,
					    Float_t& d1, Float_t& d2)
{
  const HPointF &A = c.A, &B = c.B, &C = c.C, &D = c.D;
  const HPointF At  = A  * t;
  const HPointF At2 = At * t;
  const HPointF Bt  = B  * t;

  const HPointF pmP = t * (At2 + Bt + C) + D - P;
  const HPointF pd1 = 3.0f * At2 + 2.0f * Bt + C;
  const HPointF pd2 = 6.0f * At  + 2.0f * B;

  d1 = pmP.Dot(pd1);
  d2 = pmP.Dot(pd2) + pd1.Dot(pd1);
}

bool TabletStrokeList::find_closest_points(Double_t x, Double_t y, Double_t z,
					   Int_t id[2], Double_t vm[2])
{
  Float_t       in_point[2] = { x, y };
  vector<Int_t> result;

  mKDTree->FindInRange(in_point, mSearchRad, result);

  if (result.empty()) return false;

  for (vector<Int_t>::iterator pi = result.begin(); pi != result.end(); ++pi)
  {
    STabletPoint &p = * mPointRefs[*pi];

    const Double_t Dsqr = sqr(x - p.x) + sqr(y - p.y) + sqr(z - p.z);
    const Double_t R    = mWidth * TMath::Power(p.p, mPressureAlpha);
    const Double_t v    = TMath::Power(Dsqr / sqr(R), mPotentialExp);

    if (v > vm[0])
    {
      vm[1] = vm[0]; id[1] = id[0];
      vm[0] = v;     id[0] = *pi;
    }
    else if (v > vm[1])
    {
      vm[1] = v; id[1] = *pi;
    }
  }

  return true;
}

void TabletStrokeList::get_linear_approx(Double_t x, Double_t y, Double_t z,
					 Int_t id[2], Double_t vm[2],
					 Double_t& value, STabletPoint* point)
{
  value = vm[0];  if (point) *point = *mPointRefs[id[0]];

  if (id[1] == -1 || TMath::Abs(id[0] - id[1]) != 1) return;

  if (id[0] > id[1])  swap(id[0], id[1]);
  STabletPoint &a = * mPointRefs[id[0]];
  STabletPoint &b = * mPointRefs[id[1]];

  // Stroke boundary?
  if (a.t > b.t) return;

  HPointF      P(x, y, z);
  STabletPoint atob = b - a;
  HPointF      atop = P - a;
  Float_t      f    = atob.Dot(atop) / atob.Mag2();

  // Check if we are off one or the other edge:
  if (f <= -0.05 || f >= 1.05f) return;

  STabletPoint p = (1.0f - f)*a + f*b;

  const Double_t Dsqr = sqr(x - p.x) + sqr(y - p.y) + sqr(z - p.z);
  const Double_t R    = mWidth * TMath::Power(p.p, mPressureAlpha);

  value = TMath::Power(Dsqr / sqr(R), mPotentialExp);

  if (point) *point = p;
}

void TabletStrokeList::get_cubic_approx(Double_t x, Double_t y, Double_t z,
					Int_t id[2], Double_t vm[2],
					Double_t& value, STabletPoint* point)
{
  value = vm[0]; if (point) *point = *mPointRefs[id[0]];

  if (id[1] == -1 || TMath::Abs(id[0] - id[1]) != 1) return;

  if (id[0] > id[1])  swap(id[0], id[1]);
  STabletPoint &a = * mPointRefs[id[0]];
  STabletPoint &b = * mPointRefs[id[1]];

  // Stroke boundary?
  if (a.t > b.t) return;

  // Use "linear" time as starting approximation.
  HPointF      P(x, y, z);
  STabletPoint atob = b - a;
  HPointF      atop = P - a;
  Float_t      f    = atob.Dot(atop) / atob.Mag2();

  CCoefs &c = mCCoefs[id[0]];
  Float_t T = f * atob.t;
  Float_t d1, d2;
  Int_t N = 0;
  do
  {
    distance_derivatives(T, P, c, d1, d2);
    T -= d1 / d2;
  } while (TMath::Abs(d1) > 1e-7f && ++N < 20);

  if (bMakeCubHistos && !point)
  {
    mHN->Fill(N);
    mHCubTimevsTime->Fill(f, T/atob.t);
    mHCubTimevsN->Fill(N, T/atob.t);
    mHDeriv->Fill(1e6f*d1);
    if (N >= 20)
    {
      mHCubTime20->Fill(T/atob.t);
      mHDeriv20->Fill(1e3f*d1);
    }
  }

  if (T < -0.05f*atob.t || T > 1.05f*atob.t) return;

  const Float_t T2 = T * T;
  STabletPoint p = T2*T * c.A + T2 * c.B + T * c.C + c.D;

  const Double_t Dsqr = sqr(x - p.x) + sqr(y - p.y) + sqr(z - p.z);
  const Double_t R    = mWidth * TMath::Power(p.p, mPressureAlpha);

  value = TMath::Power(Dsqr / sqr(R), mPotentialExp);

  if (point) *point = p;
}

void TabletStrokeList::add_gradient(HPointD& g, Double_t x, Double_t y, Double_t z,
				    Double_t value, STabletPoint* point)
{
  const Double_t Dsqr = sqr(x - point->x) + sqr(y - point->y) + sqr(z - point->z);
  const Double_t f    = 2.0 * mPotentialExp * value / Dsqr;

  g.x += f * (x - point->x);
  g.y += f * (y - point->y);
  g.z += f * (z - point->z);
}

Double_t TabletStrokeList::GTSIsoFunc(Double_t x, Double_t y, Double_t z)
{
  Int_t    id[2] = { -1, -1 };
  Double_t vm[2] = {  0,  0 };

  if ( ! find_closest_points(x, y, z, id, vm))
  {
    return 0;
  }

  switch (mAlgorithm)
  {
    case PA_StrongestPoint:
    {
      return vm[0];
    }
    case PA_TwoStrongestPoints:
    {
      return vm[0] + vm[1];
    }
    case PA_LinearInterpolation:
    {
      Double_t value;
      get_linear_approx(x, y, z, id, vm, value);
      return value;
    }
    case PA_CubicInterpolation:
    {
      Double_t value;
      get_cubic_approx(x, y, z, id, vm, value);
      return value;
    }
  }

  // gcc was complaining ...
  return 0;
}

Double_t TabletStrokeList::GTSIsoGradient(Double_t x, Double_t y, Double_t z, HPointD& g)
{
  g.Zero();

  Int_t    id[2] = { -1, -1 };
  Double_t vm[2] = {  0,  0 };

  if ( ! find_closest_points(x, y, z, id, vm))
  {
    return 0;
  }

  switch (mAlgorithm)
  {
    case PA_StrongestPoint:
    {
      add_gradient(g, x, y, z, vm[0], mPointRefs[id[0]]);
      return vm[0];
    }
    case PA_TwoStrongestPoints:
    {
      add_gradient(g, x, y, z, vm[0], mPointRefs[id[0]]);
      add_gradient(g, x, y, z, vm[1], mPointRefs[id[1]]);
      return vm[0] + vm[1];
    }
    case PA_LinearInterpolation:
    {
      Double_t     value;
      STabletPoint point;
      get_linear_approx(x, y, z, id, vm, value, &point);
      add_gradient(g, x, y, z, value, &point);
      return value;
    }
    case PA_CubicInterpolation:
    {
      Double_t     value;
      STabletPoint point;
      get_cubic_approx(x, y, z, id, vm, value, &point);
      add_gradient(g, x, y, z, value, &point);
      return value;
    }
  }

  // gcc was complaining ...
  return 0;
}

void TabletStrokeList::GTSIsoEnd()
{
  if (bMakeCubHistos && mAlgorithm == PA_CubicInterpolation)
  {
    TCanvas *canvas = XTReqCanvas::Request("StrokeList", "StrokeList Cubics", 1536, 768, 3, 2);
    canvas->cd(1); mHN->Draw();
    canvas->cd(2); mHCubTimevsTime->Draw();
    canvas->cd(3); mHCubTimevsN->Draw();
    canvas->cd(4); mHCubTime20->Draw();
    canvas->cd(5); mHDeriv->Draw();
    canvas->cd(6); mHDeriv20->Draw();
    XTReqPadUpdate::Update(canvas);
  }
}
 TabletStrokeList.cxx:1
 TabletStrokeList.cxx:2
 TabletStrokeList.cxx:3
 TabletStrokeList.cxx:4
 TabletStrokeList.cxx:5
 TabletStrokeList.cxx:6
 TabletStrokeList.cxx:7
 TabletStrokeList.cxx:8
 TabletStrokeList.cxx:9
 TabletStrokeList.cxx:10
 TabletStrokeList.cxx:11
 TabletStrokeList.cxx:12
 TabletStrokeList.cxx:13
 TabletStrokeList.cxx:14
 TabletStrokeList.cxx:15
 TabletStrokeList.cxx:16
 TabletStrokeList.cxx:17
 TabletStrokeList.cxx:18
 TabletStrokeList.cxx:19
 TabletStrokeList.cxx:20
 TabletStrokeList.cxx:21
 TabletStrokeList.cxx:22
 TabletStrokeList.cxx:23
 TabletStrokeList.cxx:24
 TabletStrokeList.cxx:25
 TabletStrokeList.cxx:26
 TabletStrokeList.cxx:27
 TabletStrokeList.cxx:28
 TabletStrokeList.cxx:29
 TabletStrokeList.cxx:30
 TabletStrokeList.cxx:31
 TabletStrokeList.cxx:32
 TabletStrokeList.cxx:33
 TabletStrokeList.cxx:34
 TabletStrokeList.cxx:35
 TabletStrokeList.cxx:36
 TabletStrokeList.cxx:37
 TabletStrokeList.cxx:38
 TabletStrokeList.cxx:39
 TabletStrokeList.cxx:40
 TabletStrokeList.cxx:41
 TabletStrokeList.cxx:42
 TabletStrokeList.cxx:43
 TabletStrokeList.cxx:44
 TabletStrokeList.cxx:45
 TabletStrokeList.cxx:46
 TabletStrokeList.cxx:47
 TabletStrokeList.cxx:48
 TabletStrokeList.cxx:49
 TabletStrokeList.cxx:50
 TabletStrokeList.cxx:51
 TabletStrokeList.cxx:52
 TabletStrokeList.cxx:53
 TabletStrokeList.cxx:54
 TabletStrokeList.cxx:55
 TabletStrokeList.cxx:56
 TabletStrokeList.cxx:57
 TabletStrokeList.cxx:58
 TabletStrokeList.cxx:59
 TabletStrokeList.cxx:60
 TabletStrokeList.cxx:61
 TabletStrokeList.cxx:62
 TabletStrokeList.cxx:63
 TabletStrokeList.cxx:64
 TabletStrokeList.cxx:65
 TabletStrokeList.cxx:66
 TabletStrokeList.cxx:67
 TabletStrokeList.cxx:68
 TabletStrokeList.cxx:69
 TabletStrokeList.cxx:70
 TabletStrokeList.cxx:71
 TabletStrokeList.cxx:72
 TabletStrokeList.cxx:73
 TabletStrokeList.cxx:74
 TabletStrokeList.cxx:75
 TabletStrokeList.cxx:76
 TabletStrokeList.cxx:77
 TabletStrokeList.cxx:78
 TabletStrokeList.cxx:79
 TabletStrokeList.cxx:80
 TabletStrokeList.cxx:81
 TabletStrokeList.cxx:82
 TabletStrokeList.cxx:83
 TabletStrokeList.cxx:84
 TabletStrokeList.cxx:85
 TabletStrokeList.cxx:86
 TabletStrokeList.cxx:87
 TabletStrokeList.cxx:88
 TabletStrokeList.cxx:89
 TabletStrokeList.cxx:90
 TabletStrokeList.cxx:91
 TabletStrokeList.cxx:92
 TabletStrokeList.cxx:93
 TabletStrokeList.cxx:94
 TabletStrokeList.cxx:95
 TabletStrokeList.cxx:96
 TabletStrokeList.cxx:97
 TabletStrokeList.cxx:98
 TabletStrokeList.cxx:99
 TabletStrokeList.cxx:100
 TabletStrokeList.cxx:101
 TabletStrokeList.cxx:102
 TabletStrokeList.cxx:103
 TabletStrokeList.cxx:104
 TabletStrokeList.cxx:105
 TabletStrokeList.cxx:106
 TabletStrokeList.cxx:107
 TabletStrokeList.cxx:108
 TabletStrokeList.cxx:109
 TabletStrokeList.cxx:110
 TabletStrokeList.cxx:111
 TabletStrokeList.cxx:112
 TabletStrokeList.cxx:113
 TabletStrokeList.cxx:114
 TabletStrokeList.cxx:115
 TabletStrokeList.cxx:116
 TabletStrokeList.cxx:117
 TabletStrokeList.cxx:118
 TabletStrokeList.cxx:119
 TabletStrokeList.cxx:120
 TabletStrokeList.cxx:121
 TabletStrokeList.cxx:122
 TabletStrokeList.cxx:123
 TabletStrokeList.cxx:124
 TabletStrokeList.cxx:125
 TabletStrokeList.cxx:126
 TabletStrokeList.cxx:127
 TabletStrokeList.cxx:128
 TabletStrokeList.cxx:129
 TabletStrokeList.cxx:130
 TabletStrokeList.cxx:131
 TabletStrokeList.cxx:132
 TabletStrokeList.cxx:133
 TabletStrokeList.cxx:134
 TabletStrokeList.cxx:135
 TabletStrokeList.cxx:136
 TabletStrokeList.cxx:137
 TabletStrokeList.cxx:138
 TabletStrokeList.cxx:139
 TabletStrokeList.cxx:140
 TabletStrokeList.cxx:141
 TabletStrokeList.cxx:142
 TabletStrokeList.cxx:143
 TabletStrokeList.cxx:144
 TabletStrokeList.cxx:145
 TabletStrokeList.cxx:146
 TabletStrokeList.cxx:147
 TabletStrokeList.cxx:148
 TabletStrokeList.cxx:149
 TabletStrokeList.cxx:150
 TabletStrokeList.cxx:151
 TabletStrokeList.cxx:152
 TabletStrokeList.cxx:153
 TabletStrokeList.cxx:154
 TabletStrokeList.cxx:155
 TabletStrokeList.cxx:156
 TabletStrokeList.cxx:157
 TabletStrokeList.cxx:158
 TabletStrokeList.cxx:159
 TabletStrokeList.cxx:160
 TabletStrokeList.cxx:161
 TabletStrokeList.cxx:162
 TabletStrokeList.cxx:163
 TabletStrokeList.cxx:164
 TabletStrokeList.cxx:165
 TabletStrokeList.cxx:166
 TabletStrokeList.cxx:167
 TabletStrokeList.cxx:168
 TabletStrokeList.cxx:169
 TabletStrokeList.cxx:170
 TabletStrokeList.cxx:171
 TabletStrokeList.cxx:172
 TabletStrokeList.cxx:173
 TabletStrokeList.cxx:174
 TabletStrokeList.cxx:175
 TabletStrokeList.cxx:176
 TabletStrokeList.cxx:177
 TabletStrokeList.cxx:178
 TabletStrokeList.cxx:179
 TabletStrokeList.cxx:180
 TabletStrokeList.cxx:181
 TabletStrokeList.cxx:182
 TabletStrokeList.cxx:183
 TabletStrokeList.cxx:184
 TabletStrokeList.cxx:185
 TabletStrokeList.cxx:186
 TabletStrokeList.cxx:187
 TabletStrokeList.cxx:188
 TabletStrokeList.cxx:189
 TabletStrokeList.cxx:190
 TabletStrokeList.cxx:191
 TabletStrokeList.cxx:192
 TabletStrokeList.cxx:193
 TabletStrokeList.cxx:194
 TabletStrokeList.cxx:195
 TabletStrokeList.cxx:196
 TabletStrokeList.cxx:197
 TabletStrokeList.cxx:198
 TabletStrokeList.cxx:199
 TabletStrokeList.cxx:200
 TabletStrokeList.cxx:201
 TabletStrokeList.cxx:202
 TabletStrokeList.cxx:203
 TabletStrokeList.cxx:204
 TabletStrokeList.cxx:205
 TabletStrokeList.cxx:206
 TabletStrokeList.cxx:207
 TabletStrokeList.cxx:208
 TabletStrokeList.cxx:209
 TabletStrokeList.cxx:210
 TabletStrokeList.cxx:211
 TabletStrokeList.cxx:212
 TabletStrokeList.cxx:213
 TabletStrokeList.cxx:214
 TabletStrokeList.cxx:215
 TabletStrokeList.cxx:216
 TabletStrokeList.cxx:217
 TabletStrokeList.cxx:218
 TabletStrokeList.cxx:219
 TabletStrokeList.cxx:220
 TabletStrokeList.cxx:221
 TabletStrokeList.cxx:222
 TabletStrokeList.cxx:223
 TabletStrokeList.cxx:224
 TabletStrokeList.cxx:225
 TabletStrokeList.cxx:226
 TabletStrokeList.cxx:227
 TabletStrokeList.cxx:228
 TabletStrokeList.cxx:229
 TabletStrokeList.cxx:230
 TabletStrokeList.cxx:231
 TabletStrokeList.cxx:232
 TabletStrokeList.cxx:233
 TabletStrokeList.cxx:234
 TabletStrokeList.cxx:235
 TabletStrokeList.cxx:236
 TabletStrokeList.cxx:237
 TabletStrokeList.cxx:238
 TabletStrokeList.cxx:239
 TabletStrokeList.cxx:240
 TabletStrokeList.cxx:241
 TabletStrokeList.cxx:242
 TabletStrokeList.cxx:243
 TabletStrokeList.cxx:244
 TabletStrokeList.cxx:245
 TabletStrokeList.cxx:246
 TabletStrokeList.cxx:247
 TabletStrokeList.cxx:248
 TabletStrokeList.cxx:249
 TabletStrokeList.cxx:250
 TabletStrokeList.cxx:251
 TabletStrokeList.cxx:252
 TabletStrokeList.cxx:253
 TabletStrokeList.cxx:254
 TabletStrokeList.cxx:255
 TabletStrokeList.cxx:256
 TabletStrokeList.cxx:257
 TabletStrokeList.cxx:258
 TabletStrokeList.cxx:259
 TabletStrokeList.cxx:260
 TabletStrokeList.cxx:261
 TabletStrokeList.cxx:262
 TabletStrokeList.cxx:263
 TabletStrokeList.cxx:264
 TabletStrokeList.cxx:265
 TabletStrokeList.cxx:266
 TabletStrokeList.cxx:267
 TabletStrokeList.cxx:268
 TabletStrokeList.cxx:269
 TabletStrokeList.cxx:270
 TabletStrokeList.cxx:271
 TabletStrokeList.cxx:272
 TabletStrokeList.cxx:273
 TabletStrokeList.cxx:274
 TabletStrokeList.cxx:275
 TabletStrokeList.cxx:276
 TabletStrokeList.cxx:277
 TabletStrokeList.cxx:278
 TabletStrokeList.cxx:279
 TabletStrokeList.cxx:280
 TabletStrokeList.cxx:281
 TabletStrokeList.cxx:282
 TabletStrokeList.cxx:283
 TabletStrokeList.cxx:284
 TabletStrokeList.cxx:285
 TabletStrokeList.cxx:286
 TabletStrokeList.cxx:287
 TabletStrokeList.cxx:288
 TabletStrokeList.cxx:289
 TabletStrokeList.cxx:290
 TabletStrokeList.cxx:291
 TabletStrokeList.cxx:292
 TabletStrokeList.cxx:293
 TabletStrokeList.cxx:294
 TabletStrokeList.cxx:295
 TabletStrokeList.cxx:296
 TabletStrokeList.cxx:297
 TabletStrokeList.cxx:298
 TabletStrokeList.cxx:299
 TabletStrokeList.cxx:300
 TabletStrokeList.cxx:301
 TabletStrokeList.cxx:302
 TabletStrokeList.cxx:303
 TabletStrokeList.cxx:304
 TabletStrokeList.cxx:305
 TabletStrokeList.cxx:306
 TabletStrokeList.cxx:307
 TabletStrokeList.cxx:308
 TabletStrokeList.cxx:309
 TabletStrokeList.cxx:310
 TabletStrokeList.cxx:311
 TabletStrokeList.cxx:312
 TabletStrokeList.cxx:313
 TabletStrokeList.cxx:314
 TabletStrokeList.cxx:315
 TabletStrokeList.cxx:316
 TabletStrokeList.cxx:317
 TabletStrokeList.cxx:318
 TabletStrokeList.cxx:319
 TabletStrokeList.cxx:320
 TabletStrokeList.cxx:321
 TabletStrokeList.cxx:322
 TabletStrokeList.cxx:323
 TabletStrokeList.cxx:324
 TabletStrokeList.cxx:325
 TabletStrokeList.cxx:326
 TabletStrokeList.cxx:327
 TabletStrokeList.cxx:328
 TabletStrokeList.cxx:329
 TabletStrokeList.cxx:330
 TabletStrokeList.cxx:331
 TabletStrokeList.cxx:332
 TabletStrokeList.cxx:333
 TabletStrokeList.cxx:334
 TabletStrokeList.cxx:335
 TabletStrokeList.cxx:336
 TabletStrokeList.cxx:337
 TabletStrokeList.cxx:338
 TabletStrokeList.cxx:339
 TabletStrokeList.cxx:340
 TabletStrokeList.cxx:341
 TabletStrokeList.cxx:342
 TabletStrokeList.cxx:343
 TabletStrokeList.cxx:344
 TabletStrokeList.cxx:345
 TabletStrokeList.cxx:346
 TabletStrokeList.cxx:347
 TabletStrokeList.cxx:348
 TabletStrokeList.cxx:349
 TabletStrokeList.cxx:350
 TabletStrokeList.cxx:351
 TabletStrokeList.cxx:352
 TabletStrokeList.cxx:353
 TabletStrokeList.cxx:354
 TabletStrokeList.cxx:355
 TabletStrokeList.cxx:356
 TabletStrokeList.cxx:357
 TabletStrokeList.cxx:358
 TabletStrokeList.cxx:359
 TabletStrokeList.cxx:360
 TabletStrokeList.cxx:361
 TabletStrokeList.cxx:362
 TabletStrokeList.cxx:363
 TabletStrokeList.cxx:364
 TabletStrokeList.cxx:365
 TabletStrokeList.cxx:366
 TabletStrokeList.cxx:367
 TabletStrokeList.cxx:368
 TabletStrokeList.cxx:369
 TabletStrokeList.cxx:370
 TabletStrokeList.cxx:371
 TabletStrokeList.cxx:372
 TabletStrokeList.cxx:373
 TabletStrokeList.cxx:374
 TabletStrokeList.cxx:375
 TabletStrokeList.cxx:376
 TabletStrokeList.cxx:377
 TabletStrokeList.cxx:378
 TabletStrokeList.cxx:379
 TabletStrokeList.cxx:380
 TabletStrokeList.cxx:381
 TabletStrokeList.cxx:382
 TabletStrokeList.cxx:383
 TabletStrokeList.cxx:384
 TabletStrokeList.cxx:385
 TabletStrokeList.cxx:386
 TabletStrokeList.cxx:387
 TabletStrokeList.cxx:388
 TabletStrokeList.cxx:389
 TabletStrokeList.cxx:390
 TabletStrokeList.cxx:391
 TabletStrokeList.cxx:392
 TabletStrokeList.cxx:393
 TabletStrokeList.cxx:394
 TabletStrokeList.cxx:395
 TabletStrokeList.cxx:396
 TabletStrokeList.cxx:397
 TabletStrokeList.cxx:398
 TabletStrokeList.cxx:399
 TabletStrokeList.cxx:400
 TabletStrokeList.cxx:401
 TabletStrokeList.cxx:402
 TabletStrokeList.cxx:403
 TabletStrokeList.cxx:404
 TabletStrokeList.cxx:405
 TabletStrokeList.cxx:406
 TabletStrokeList.cxx:407
 TabletStrokeList.cxx:408
 TabletStrokeList.cxx:409
 TabletStrokeList.cxx:410
 TabletStrokeList.cxx:411
 TabletStrokeList.cxx:412
 TabletStrokeList.cxx:413
 TabletStrokeList.cxx:414
 TabletStrokeList.cxx:415
 TabletStrokeList.cxx:416
 TabletStrokeList.cxx:417
 TabletStrokeList.cxx:418
 TabletStrokeList.cxx:419
 TabletStrokeList.cxx:420
 TabletStrokeList.cxx:421
 TabletStrokeList.cxx:422
 TabletStrokeList.cxx:423
 TabletStrokeList.cxx:424
 TabletStrokeList.cxx:425
 TabletStrokeList.cxx:426
 TabletStrokeList.cxx:427
 TabletStrokeList.cxx:428
 TabletStrokeList.cxx:429
 TabletStrokeList.cxx:430
 TabletStrokeList.cxx:431
 TabletStrokeList.cxx:432
 TabletStrokeList.cxx:433
 TabletStrokeList.cxx:434
 TabletStrokeList.cxx:435
 TabletStrokeList.cxx:436
 TabletStrokeList.cxx:437
 TabletStrokeList.cxx:438
 TabletStrokeList.cxx:439
 TabletStrokeList.cxx:440
 TabletStrokeList.cxx:441
 TabletStrokeList.cxx:442
 TabletStrokeList.cxx:443
 TabletStrokeList.cxx:444
 TabletStrokeList.cxx:445
 TabletStrokeList.cxx:446