~efargaspro/+junk/codeblocks-16.01-release

« back to all changes in this revision

Viewing changes to src/plugins/contrib/source_exporter/wxPdfDocument/src/pdfxml.cpp

  • Committer: damienlmoore at gmail
  • Date: 2016-02-02 02:43:22 UTC
  • Revision ID: damienlmoore@gmail.com-20160202024322-yql5qmtbwdyamdwd
Code::BlocksĀ 16.01

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
///////////////////////////////////////////////////////////////////////////////
 
2
// Name:        pdfxml.cpp
 
3
// Purpose:     
 
4
// Author:      Ulrich Telle
 
5
// Modified by:
 
6
// Created:     2005-12-03
 
7
// RCS-ID:      $$
 
8
// Copyright:   (c) Ulrich Telle
 
9
// Licence:     wxWindows licence + RDS Data Security license
 
10
///////////////////////////////////////////////////////////////////////////////
 
11
 
 
12
/// \file pdfxml.cpp Implementation of the wxPdfDocument markup
 
13
 
 
14
// For compilers that support precompilation, includes <wx.h>.
 
15
#include <wx/wxprec.h>
 
16
 
 
17
#ifdef __BORLANDC__
 
18
#pragma hdrstop
 
19
#endif
 
20
 
 
21
#ifndef WX_PRECOMP
 
22
#include <wx/wx.h>
 
23
#endif
 
24
 
 
25
// includes
 
26
#include <wx/sstream.h>
 
27
 
 
28
#include "wx/pdfdocument.h"
 
29
#include "wx/pdfutility.h"
 
30
#include "wx/pdfxml.h"
 
31
 
 
32
static wxString
 
33
GetNodeContent(const wxXmlNode *node)
 
34
{
 
35
  const wxXmlNode *n = node;
 
36
  if (n == NULL) return wxEmptyString;
 
37
  n = n->GetChildren();
 
38
  while (n)
 
39
  {
 
40
    if (n->GetType() == wxXML_TEXT_NODE ||
 
41
        n->GetType() == wxXML_CDATA_SECTION_NODE)
 
42
      return n->GetContent();
 
43
    n = n->GetNext();
 
44
  }
 
45
  return wxEmptyString;
 
46
}
 
47
 
 
48
static wxString
 
49
GetXmlAttribute(const wxXmlNode* node, const wxString& attrName, const wxString& defaultVal)
 
50
{
 
51
#if wxCHECK_VERSION(2,9,0)
 
52
  return node->GetAttribute(attrName, defaultVal);
 
53
#else
 
54
  return node->GetPropVal(attrName, defaultVal);
 
55
#endif
 
56
}
 
57
 
 
58
// --- wxPdfCellContext
 
59
 
 
60
wxPdfCellContext::wxPdfCellContext(double maxWidth, wxPdfAlignment hAlign, wxPdfAlignment vAlign)
 
61
{
 
62
  m_maxWidth = maxWidth;
 
63
  m_hAlign = hAlign;
 
64
  m_vAlign = vAlign;
 
65
  m_currentLine = 0;
 
66
  m_currentContext = 0;
 
67
  m_aligned = false;
 
68
  m_fillStyle = 0;
 
69
  m_lastChar = 0;
 
70
  m_spaceWidth = 0;
 
71
  m_lineDelta = 0;
 
72
  m_height = 0;
 
73
  m_table = NULL;
 
74
  AddLine();
 
75
}
 
76
 
 
77
wxPdfCellContext::~wxPdfCellContext()
 
78
{
 
79
  size_t j;
 
80
  for (j = 0; j < m_contexts.GetCount(); j++)
 
81
  {
 
82
    wxPdfCellContext* context = static_cast<wxPdfCellContext*>(m_contexts[j]);
 
83
    delete context;
 
84
  }
 
85
  if (m_table != NULL)
 
86
  {
 
87
    delete m_table;
 
88
  }
 
89
}
 
90
 
 
91
void
 
92
wxPdfCellContext::AddLine()
 
93
{
 
94
  m_linewidth.Add(0);
 
95
  m_spaces.Add(0);
 
96
}
 
97
 
 
98
void
 
99
wxPdfCellContext::AddLastLineValues(double width, int spaces)
 
100
{
 
101
  m_linewidth.Last() += width;
 
102
  m_spaces.Last() += spaces;
 
103
}
 
104
 
 
105
void
 
106
wxPdfCellContext::AddCurrentLineWidth(double width)
 
107
{
 
108
  if (m_currentLine < m_linewidth.GetCount())
 
109
  {
 
110
    m_linewidth[m_currentLine] += width;
 
111
  }
 
112
}
 
113
 
 
114
void
 
115
wxPdfCellContext::AddCurrentLineSpaces(int spaces)
 
116
{
 
117
  if (m_currentLine < m_spaces.GetCount())
 
118
  {
 
119
    m_spaces[m_currentLine] += spaces;
 
120
  }
 
121
}
 
122
 
 
123
void
 
124
wxPdfCellContext::MarkLastLine()
 
125
{
 
126
  if (m_spaces.Last() > 0)
 
127
  {
 
128
    m_spaces.Last() *= -1;
 
129
  }
 
130
}
 
131
 
 
132
bool
 
133
wxPdfCellContext::IsCurrentLineMarked()
 
134
{
 
135
  bool marked = false;
 
136
  if (m_currentLine < m_linewidth.GetCount())
 
137
  {
 
138
    marked = (m_spaces[m_currentLine] < 0);
 
139
  }
 
140
  return marked;
 
141
}
 
142
 
 
143
 
 
144
void
 
145
wxPdfCellContext::IncrementCurrentLine()
 
146
{
 
147
  if (m_currentLine < m_linewidth.GetCount()-1)
 
148
  {
 
149
    m_currentLine++;
 
150
  }
 
151
  m_aligned = false;
 
152
}
 
153
 
 
154
double
 
155
wxPdfCellContext::GetLineDelta()
 
156
{
 
157
  if (!m_aligned)
 
158
  {
 
159
    m_lineDelta = m_maxWidth - GetCurrentLineWidth();
 
160
  }
 
161
  return m_lineDelta;
 
162
}
 
163
 
 
164
double
 
165
wxPdfCellContext::GetCurrentLineWidth()
 
166
{
 
167
  double linewidth = 0;
 
168
  if (m_currentLine < m_linewidth.GetCount())
 
169
  {
 
170
    linewidth = m_linewidth[m_currentLine];
 
171
  }
 
172
  return linewidth;
 
173
}
 
174
 
 
175
double
 
176
wxPdfCellContext::GetLastLineWidth()
 
177
{
 
178
  return m_linewidth.Last();
 
179
}
 
180
 
 
181
int
 
182
wxPdfCellContext::GetCurrentLineSpaces()
 
183
{
 
184
  int spaces = 0;
 
185
  if (m_currentLine < m_spaces.GetCount())
 
186
  {
 
187
    spaces = m_spaces[m_currentLine];
 
188
    if (spaces < 0) spaces = -spaces;
 
189
  }
 
190
  return spaces;
 
191
}
 
192
 
 
193
void
 
194
wxPdfCellContext::IncrementCurrentContext()
 
195
{
 
196
  if (m_currentContext < m_contexts.GetCount()-1)
 
197
  {
 
198
    m_currentContext++;
 
199
  }
 
200
}
 
201
 
 
202
wxPdfCellContext*
 
203
wxPdfCellContext::GetCurrentContext()
 
204
{
 
205
  wxPdfCellContext* context = NULL;
 
206
  if (m_currentContext < m_contexts.GetCount())
 
207
  {
 
208
    context = static_cast<wxPdfCellContext*>(m_contexts[m_currentContext]);
 
209
  }
 
210
  return context;
 
211
}
 
212
 
 
213
void
 
214
wxPdfCellContext::AppendContext(wxPdfCellContext* context)
 
215
{
 
216
  m_contexts.Add(context);
 
217
}
 
218
 
 
219
// --- wxPdfTableCell
 
220
 
 
221
wxPdfTableCell::wxPdfTableCell(wxXmlNode* cell, unsigned int row, unsigned int col, unsigned int rows, unsigned int cols)
 
222
{
 
223
  m_cell   = cell;
 
224
  m_width  = -1.0;
 
225
  m_height = -1.0;
 
226
  m_row = row;
 
227
  m_col = col;
 
228
  m_rowSpan = rows;
 
229
  m_colSpan = cols;
 
230
  
 
231
  SetBorder(wxPDF_BORDER_NONE);
 
232
  m_context = NULL;
 
233
  m_hasCellColour = false;
 
234
}
 
235
 
 
236
wxPdfTableCell::~wxPdfTableCell()
 
237
{
 
238
  if (m_context != NULL)
 
239
  {
 
240
    delete m_context;
 
241
  }
 
242
}
 
243
 
 
244
// --- wxPdfTable
 
245
 
 
246
wxPdfTable::wxPdfTable(wxPdfDocument* document)
 
247
{
 
248
  m_document = document;
 
249
  m_nRows = 0;
 
250
  m_nCols = 0;
 
251
  m_totalWidth  = 0;
 
252
  m_totalHeight = 0;
 
253
  m_headHeight  = 0;
 
254
  m_pad = 0;
 
255
  m_headRowFirst = 0;
 
256
  m_headRowLast  = 0;
 
257
  m_bodyRowFirst = 0;
 
258
  m_bodyRowLast  = 0;
 
259
}
 
260
 
 
261
wxPdfTable::~wxPdfTable()
 
262
{
 
263
  // Free all cells
 
264
  wxPdfCellHashMap::iterator cell;
 
265
  for (cell = m_table.begin(); cell != m_table.end(); cell++)
 
266
  {
 
267
    if (cell->second != NULL)
 
268
    {
 
269
      delete cell->second;
 
270
    }
 
271
  }
 
272
}
 
273
 
 
274
void
 
275
wxPdfTable::SetCellDimensions(double maxWidth)
 
276
{
 
277
  unsigned int row, col;
 
278
  double defaultWidth = (m_nCols > 0) ? maxWidth / m_nCols : 0;
 
279
  for (col = 0; col < m_nCols; col++)
 
280
  {
 
281
    if (col >= m_colWidths.size() || m_colWidths[col] <= 0)
 
282
    {
 
283
      SetColumnWidth(col, defaultWidth);
 
284
    }
 
285
  }
 
286
 
 
287
  if (m_totalWidth > maxWidth)
 
288
  {
 
289
    double factor = maxWidth / m_totalWidth;
 
290
    for (col = 0; col < m_colWidths.size(); col++)
 
291
    {
 
292
      m_colWidths[col] /= factor;
 
293
    }
 
294
  }
 
295
 
 
296
  double rowHeight;
 
297
  wxPdfBoolHashMap rowSpans;
 
298
  unsigned int rowSpan;
 
299
  unsigned int maxRowSpan = 1;
 
300
  for (row = 0; row < m_nRows; row++)
 
301
  {
 
302
    rowHeight = 0;
 
303
    for (col = 0; col < m_nCols; col++)
 
304
    {
 
305
      wxPdfCellHashMap::iterator foundCell = m_table.find((row << 16) | col);
 
306
      if (foundCell != m_table.end())
 
307
      {
 
308
        wxPdfTableCell* cell = foundCell->second;
 
309
        int span;
 
310
        double cellWidth = 0;
 
311
        for (span = 0; span < (int) cell->GetColSpan(); span++)
 
312
        {
 
313
          cellWidth += m_colWidths[col+span];
 
314
        }
 
315
        if (cellWidth > 2*m_pad) cellWidth -= (2*m_pad);
 
316
        cell->SetWidth(cellWidth);
 
317
        wxPdfCellContext* cellContext = new wxPdfCellContext(cellWidth, cell->GetHAlign());
 
318
        cell->SetContext(cellContext);
 
319
        m_document->PrepareXmlCell(cell->GetXmlNode(), *cellContext);
 
320
        double height = cellContext->GetHeight() + 2*m_pad;
 
321
        cell->SetHeight(height);
 
322
        rowSpan = cell->GetRowSpan();
 
323
        rowSpans[rowSpan] = true;
 
324
        if (rowSpan == 1 && height > rowHeight)
 
325
        {
 
326
          rowHeight = height;
 
327
        }
 
328
        else
 
329
        {
 
330
          if (rowSpan > maxRowSpan)
 
331
          {
 
332
            maxRowSpan = rowSpan;
 
333
          }
 
334
        }
 
335
      }
 
336
    }
 
337
    m_rowHeights[row] = (rowHeight < m_minHeights[row]) ? m_minHeights[row] : rowHeight;
 
338
  }
 
339
 
 
340
  for (rowSpan = 2; rowSpan <= maxRowSpan; rowSpan++)
 
341
  {
 
342
    wxPdfBoolHashMap::iterator currentRowSpan = rowSpans.find(rowSpan);
 
343
    if (currentRowSpan != rowSpans.end())
 
344
    {
 
345
      for (row = 0; row < m_nRows; row++)
 
346
      {
 
347
        rowHeight = 0;
 
348
        for (col = 0; col < m_nCols; col++)
 
349
        {
 
350
          wxPdfCellHashMap::iterator foundCell = m_table.find((row << 16) | col);
 
351
          if (foundCell != m_table.end())
 
352
          {
 
353
            wxPdfTableCell* cell = foundCell->second;
 
354
            if (rowSpan == cell->GetRowSpan())
 
355
            {
 
356
              rowHeight = 0;
 
357
              int span;
 
358
              for (span = cell->GetRowSpan()-1; span >= 0; span--)
 
359
              {
 
360
                rowHeight += m_rowHeights[row+span];
 
361
              }
 
362
              if (cell->GetHeight() > rowHeight)
 
363
              {
 
364
                double delta = (cell->GetHeight() - rowHeight) / cell->GetRowSpan();
 
365
                for (span = cell->GetRowSpan()-1; span >= 0; span--)
 
366
                {
 
367
                  m_rowHeights[row+span] += delta;
 
368
                }
 
369
              }
 
370
            }
 
371
          }
 
372
        }
 
373
      }
 
374
    }
 
375
  }
 
376
  m_headHeight = 0;
 
377
  for (row = m_headRowFirst; row < m_headRowLast; row++)
 
378
  {
 
379
    m_headHeight += m_rowHeights[row];
 
380
  }
 
381
  m_totalHeight = 0;
 
382
  for (row = m_bodyRowFirst; row < m_bodyRowLast; row++)
 
383
  {
 
384
    m_totalHeight += m_rowHeights[row];
 
385
  }
 
386
}
 
387
 
 
388
void
 
389
wxPdfTable::InsertCell(wxPdfTableCell* cell)
 
390
{
 
391
  unsigned int x = cell->GetCol();
 
392
  unsigned int y = cell->GetRow();
 
393
  unsigned int w = cell->GetColSpan();
 
394
  unsigned int h = cell->GetRowSpan();
 
395
  m_table[(y << 16)|x] = cell;
 
396
  if (x + w > m_nCols)
 
397
  {
 
398
    m_nCols = x + w;
 
399
  }
 
400
  if (y + h > m_nRows)
 
401
  {
 
402
    m_nRows = y + h;
 
403
  }
 
404
}
 
405
 
 
406
void
 
407
wxPdfTable::Write()
 
408
{
 
409
  bool writeHeader = m_headRowLast > m_headRowFirst;
 
410
  bool newPage = false;
 
411
  double saveLeftMargin = m_document->GetLeftMargin();
 
412
  double x, y;
 
413
  unsigned int row, headRow;
 
414
  y = m_document->GetY();
 
415
  double breakMargin = m_document->GetBreakMargin();
 
416
  double pageHeight = m_document->GetPageHeight();
 
417
  double yMax = pageHeight - breakMargin;
 
418
  if (y + m_headHeight + m_rowHeights[m_bodyRowFirst] > yMax)
 
419
  {
 
420
    newPage = true;
 
421
  }
 
422
  for (row = m_bodyRowFirst; row < m_bodyRowLast; row++)
 
423
  {
 
424
    if (!newPage && (y + m_rowHeights[row] > yMax))
 
425
    {
 
426
      newPage = true;
 
427
    }
 
428
    if (newPage)
 
429
    {
 
430
      newPage = false;
 
431
      m_document->AddPage();
 
432
      writeHeader = m_headRowLast > m_headRowFirst;
 
433
      y = m_document->GetY();
 
434
    }
 
435
    if (writeHeader)
 
436
    {
 
437
      writeHeader = false;
 
438
      for (headRow = m_headRowFirst; headRow < m_headRowLast; headRow++)
 
439
      {
 
440
        x = saveLeftMargin;
 
441
        WriteRow(headRow, x, y);
 
442
        y += m_rowHeights[headRow];
 
443
      }
 
444
    }
 
445
    x = saveLeftMargin;
 
446
    WriteRow(row, x, y);
 
447
    y += m_rowHeights[row];
 
448
  }
 
449
}
 
450
 
 
451
void
 
452
wxPdfTable::WriteRow(unsigned int row, double x, double y)
 
453
{
 
454
  bool isHeaderRow = (row >= m_headRowFirst && row < m_headRowLast);
 
455
  unsigned int col;
 
456
  unsigned int rowspan, colspan;
 
457
  double w, h;
 
458
  m_document->SetXY(x, y+m_pad);
 
459
  for (col = 0; col < m_nCols; col++)
 
460
  {
 
461
    wxPdfCellHashMap::iterator foundCell = m_table.find((row << 16) | col);
 
462
    if (foundCell != m_table.end())
 
463
    {
 
464
      wxPdfTableCell* cell = foundCell->second;
 
465
      w = 0;
 
466
      for (colspan = 0; colspan < cell->GetColSpan(); colspan++)
 
467
      {
 
468
        w += m_colWidths[col+colspan];
 
469
      }
 
470
      h = 0;
 
471
      for (rowspan = 0; rowspan < cell->GetRowSpan(); rowspan++)
 
472
      {
 
473
        h += m_rowHeights[row+rowspan];
 
474
      }
 
475
      if (cell->HasCellColour())
 
476
      {
 
477
        wxPdfColour saveFillColour = m_document->GetFillColour();
 
478
        m_document->SetFillColour(cell->GetCellColour());
 
479
        m_document->Rect(x, y, w, h, wxPDF_STYLE_FILL);
 
480
        m_document->SetFillColour(saveFillColour);
 
481
      }
 
482
      int border = cell->GetBorder();
 
483
      if ((border & wxPDF_BORDER_FRAME) == wxPDF_BORDER_FRAME)
 
484
      {
 
485
        m_document->Rect(x, y, w, h);
 
486
      }
 
487
      else
 
488
      {
 
489
        if (border & wxPDF_BORDER_LEFT)   m_document->Line(x,   y,   x,   y+h);
 
490
        if (border & wxPDF_BORDER_TOP)    m_document->Line(x,   y,   x+w, y);
 
491
        if (border & wxPDF_BORDER_BOTTOM) m_document->Line(x,   y+h, x+w, y+h);
 
492
        if (border & wxPDF_BORDER_RIGHT)  m_document->Line(x+w, y,   x+w, y+h);
 
493
      }
 
494
      m_document->SetLeftMargin(x+m_pad);
 
495
      double delta = h - cell->GetHeight();
 
496
      switch (cell->GetVAlign())
 
497
      {
 
498
        case wxPDF_ALIGN_BOTTOM:
 
499
          m_document->SetXY(x+m_pad, y+m_pad+delta);
 
500
          break;
 
501
        case wxPDF_ALIGN_MIDDLE:
 
502
          m_document->SetXY(x+m_pad, y+m_pad+0.5*delta);
 
503
          break;
 
504
        case wxPDF_ALIGN_TOP:
 
505
        default:
 
506
          m_document->SetXY(x+m_pad, y+m_pad);
 
507
          break;
 
508
      }
 
509
      m_document->WriteXmlCell(cell->GetXmlNode(), *(cell->GetContext()));
 
510
      if (isHeaderRow)
 
511
      {
 
512
        // For header rows it is necessary to prepare the cells for reprocessing
 
513
        delete cell->GetContext();
 
514
        wxPdfCellContext* cellContext = new wxPdfCellContext(cell->GetWidth(), cell->GetHAlign());
 
515
        cell->SetContext(cellContext);
 
516
        m_document->PrepareXmlCell(cell->GetXmlNode(), *cellContext);
 
517
      }
 
518
    }
 
519
    x += m_colWidths[col];
 
520
  }
 
521
}
 
522
 
 
523
void
 
524
wxPdfTable::SetColumnWidth(int col, double width)
 
525
 
526
  m_colWidths[col] = width;
 
527
  m_totalWidth += width;
 
528
}
 
529
 
 
530
// ----- wxPdfDocument
 
531
 
 
532
void
 
533
wxPdfDocument::PrepareXmlTable(wxXmlNode* node, wxPdfCellContext& context)
 
534
{
 
535
  wxPdfTable* table = context.GetTable();
 
536
  double maxWidth = context.GetMaxWidth();
 
537
  wxPdfBoolHashMap cellused;
 
538
  int coldef = 0;
 
539
  int colundef = 0;
 
540
  int row = 0;
 
541
  int col;
 
542
  int i, j;
 
543
 
 
544
  wxXmlNode *child = node->GetChildren();
 
545
  while (child)
 
546
  {
 
547
    wxString name = (child->GetName()).Lower();
 
548
    if (name == wxT("colgroup"))
 
549
    {
 
550
      wxXmlNode *colChild = child->GetChildren();
 
551
      while (colChild)
 
552
      {
 
553
        if ((colChild->GetName()).Lower() == wxT("col"))
 
554
        {
 
555
          long colspan;
 
556
          wxString span = GetXmlAttribute(colChild, wxT("span"), wxT("1"));
 
557
          if (span.Length() > 0 && span.ToLong(&colspan))
 
558
          {
 
559
            if (colspan < 1) colspan = 1;
 
560
          }
 
561
          else
 
562
          {
 
563
            colspan = 1;
 
564
          }
 
565
          double colwidth = 0;
 
566
          wxString width = GetXmlAttribute(colChild, wxT("width"), wxT("0"));
 
567
          if (width.Length() > 0)
 
568
          {
 
569
            colwidth = wxPdfUtility::String2Double(width);
 
570
            if (colwidth < 0) colwidth = 0;
 
571
          }
 
572
          for (col = 0; col < colspan; col++)
 
573
          {
 
574
            table->SetColumnWidth(coldef++, colwidth);
 
575
            if (colwidth <= 0) colundef++;
 
576
          }
 
577
        }
 
578
        colChild = colChild->GetNext();
 
579
      }
 
580
    }
 
581
    else if (name == wxT("thead") || name == wxT("tbody"))
 
582
    {
 
583
      wxString oddColour = GetXmlAttribute(child, wxT("odd"), wxT("")).Lower();
 
584
      wxString evenColour = GetXmlAttribute(child, wxT("even"), wxT("")).Lower();
 
585
      bool isHeader = name == wxT("thead");
 
586
      if (isHeader)
 
587
      {
 
588
        table->SetHeadRowFirst(row);
 
589
      }
 
590
      else
 
591
      {
 
592
        table->SetBodyRowFirst(row);
 
593
      }
 
594
      wxXmlNode *rowChild = child->GetChildren();
 
595
      int rowCount = 0;
 
596
      while (rowChild)
 
597
      {
 
598
        if ((rowChild->GetName()).Lower() == wxT("tr"))
 
599
        {
 
600
          wxString rowColour = GetXmlAttribute(rowChild, wxT("bgcolor"), wxT("")).Lower();
 
601
          rowCount++;
 
602
          if (rowColour.Length() == 0)
 
603
          {
 
604
            if (rowCount % 2 == 0)
 
605
            {
 
606
              // even row numbers
 
607
              if (evenColour.Length() > 0) rowColour = evenColour;
 
608
            }
 
609
            else
 
610
            {
 
611
              // odd row numbers
 
612
              if (oddColour.Length() > 0) rowColour = oddColour;
 
613
            }
 
614
          }
 
615
          double rowHeight = 0;
 
616
          wxString height = GetXmlAttribute(rowChild, wxT("height"), wxT("0")).Lower();
 
617
          if (height.Length() > 0)
 
618
          {
 
619
            rowHeight = wxPdfUtility::String2Double(height);
 
620
            if (rowHeight < 0) rowHeight = 0;
 
621
          }
 
622
          table->SetMinRowHeight(row, rowHeight);
 
623
          wxXmlNode *colChild = rowChild->GetChildren();
 
624
          col = 0;
 
625
          while (colChild)
 
626
          {
 
627
            if ((colChild->GetName()).Lower() == wxT("td"))
 
628
            {
 
629
              int border = wxPDF_BORDER_NONE;
 
630
              wxString strBorder = GetXmlAttribute(colChild, wxT("border"), wxT("")).Upper();
 
631
              if (strBorder.Length() > 0)
 
632
              {
 
633
                if (strBorder.Contains(wxT("L"))) border |= wxPDF_BORDER_LEFT;
 
634
                if (strBorder.Contains(wxT("T"))) border |= wxPDF_BORDER_TOP;
 
635
                if (strBorder.Contains(wxT("B"))) border |= wxPDF_BORDER_BOTTOM;
 
636
                if (strBorder.Contains(wxT("R"))) border |= wxPDF_BORDER_RIGHT;
 
637
              }
 
638
              else if (table->HasBorder())
 
639
              {
 
640
                border = wxPDF_BORDER_FRAME;
 
641
              }
 
642
 
 
643
              wxString align = GetXmlAttribute(colChild, wxT("align"), wxT("left")).Lower();
 
644
              wxPdfAlignment hAlignment = wxPDF_ALIGN_LEFT;
 
645
              if (align == wxT("right"))       hAlignment = wxPDF_ALIGN_RIGHT;
 
646
              else if (align == wxT("center")) hAlignment = wxPDF_ALIGN_CENTER;
 
647
              align = GetXmlAttribute(colChild, wxT("valign"), wxT("top")).Lower();
 
648
              wxPdfAlignment vAlignment = wxPDF_ALIGN_TOP;
 
649
              if (align == wxT("bottom"))      vAlignment = wxPDF_ALIGN_BOTTOM;
 
650
              else if (align == wxT("middle")) vAlignment = wxPDF_ALIGN_MIDDLE;
 
651
              else if (align == wxT("center")) vAlignment = wxPDF_ALIGN_MIDDLE;
 
652
 
 
653
              wxString bgColour = GetXmlAttribute(colChild, wxT("bgcolor"), wxT("")).Lower();
 
654
              wxString rowspan = GetXmlAttribute(colChild, wxT("rowspan"), wxT("1"));
 
655
              long rs;
 
656
              if (rowspan.Length() > 0 && rowspan.ToLong(&rs))
 
657
              {
 
658
                if (rs < 1) rs = 1;
 
659
              }
 
660
              else
 
661
              {
 
662
                rs = 1;
 
663
              }
 
664
              long cs;
 
665
              wxString colspan = GetXmlAttribute(colChild, wxT("colspan"), wxT("1"));
 
666
              if (colspan.Length() > 0 && colspan.ToLong(&cs))
 
667
              {
 
668
                if (cs < 1) cs = 1;
 
669
              }
 
670
              else
 
671
              {
 
672
                cs = 1;
 
673
              }
 
674
              while (cellused.find((row<<16)|col) != cellused.end())
 
675
              {
 
676
                ++col;
 
677
              }
 
678
              for (i = 0; i < cs; i++)
 
679
              {
 
680
                for (j = 0; j < rs; j++)
 
681
                {
 
682
                  cellused[((j+row)<<16)|(i+col)] = true;
 
683
                }
 
684
              }
 
685
              wxPdfTableCell* cell = new wxPdfTableCell(colChild, row, col, rs, cs);
 
686
              cell->SetHAlign(hAlignment);
 
687
              cell->SetVAlign(vAlignment);
 
688
              cell->SetBorder(border);
 
689
              if (bgColour.Length() > 0)
 
690
              {
 
691
                cell->SetCellColour(wxPdfColour(bgColour));
 
692
              }
 
693
              else if (rowColour.Length() > 0)
 
694
              {
 
695
                cell->SetCellColour(wxPdfColour(rowColour));
 
696
              }
 
697
              table->InsertCell(cell);
 
698
            }
 
699
            colChild = colChild->GetNext();
 
700
          }
 
701
          row++;
 
702
        }
 
703
        if (isHeader)
 
704
        {
 
705
          table->SetHeadRowLast(row);
 
706
        }
 
707
        else
 
708
        {
 
709
          table->SetBodyRowLast(row);
 
710
        }
 
711
        rowChild = rowChild->GetNext();
 
712
      }
 
713
    }
 
714
    child = child->GetNext();
 
715
  }
 
716
  table->SetCellDimensions(maxWidth);
 
717
  context.AddHeight(table->GetTotalHeight());
 
718
}
 
719
 
 
720
void
 
721
wxPdfDocument::WriteXmlTable(wxPdfCellContext& context)
 
722
{
 
723
  double saveLeftMargin = GetLeftMargin();
 
724
  double saveRightMargin = GetRightMargin();
 
725
  wxPdfTable* table = context.GetTable();
 
726
  double maxWidth = context.GetMaxWidth();
 
727
  double tableWidth = table->GetTotalWidth();
 
728
  double delta = 0;
 
729
  if (tableWidth < maxWidth)
 
730
  {
 
731
    wxPdfAlignment align = context.GetHAlign();
 
732
    switch (align)
 
733
    {
 
734
      case wxPDF_ALIGN_CENTER:
 
735
        delta = 0.5 * (maxWidth - tableWidth);
 
736
        break;
 
737
      case wxPDF_ALIGN_RIGHT:
 
738
        delta = maxWidth - tableWidth;
 
739
        break;
 
740
      case wxPDF_ALIGN_LEFT:
 
741
      default:
 
742
        delta = 0;
 
743
        break;
 
744
    }
 
745
  }
 
746
  // Set left and right margin
 
747
  SetLeftMargin(saveLeftMargin+delta);
 
748
  SetRightMargin(GetPageWidth() - saveLeftMargin - tableWidth - delta);
 
749
  SetXY(saveLeftMargin+delta,GetY());
 
750
 
 
751
  // Check alignment
 
752
 
 
753
  table->Write();
 
754
 
 
755
  SetLeftMargin(saveLeftMargin);
 
756
  SetRightMargin(saveRightMargin);
 
757
}
 
758
 
 
759
void
 
760
wxPdfDocument::PrepareXmlCell(wxXmlNode* node, wxPdfCellContext& context)
 
761
{
 
762
  wxPdfCellContext* newContext;
 
763
  wxXmlNode *child = node->GetChildren();
 
764
  while (child)
 
765
  {
 
766
    wxString name = (child->GetName()).Lower();
 
767
 
 
768
    if (name == wxT("b") || name == wxT("i") || name == wxT("u") ||
 
769
        name == wxT("o") || name == wxT("s") ||
 
770
        name == wxT("strong") || name == wxT("em"))
 
771
    {
 
772
      // --- Bold, Italic, Underline, Overline, Strikeout
 
773
      // --- Strong (= bold), Emphasize (= italic)
 
774
      wxString addStyle = name.Upper();
 
775
      if (name.Length() > 1)
 
776
      {
 
777
        if (name == wxT("strong"))  addStyle = wxT("B");
 
778
        else if (name == wxT("em")) addStyle = wxT("I");
 
779
      }
 
780
      wxString style = GetFontStyle();
 
781
      if (!style.Contains(addStyle))
 
782
      {
 
783
        SelectFont(wxT(""), style + addStyle, 0, false);
 
784
        PrepareXmlCell(child, context);
 
785
        SelectFont(wxT(""), style, 0, false);
 
786
      }
 
787
      else
 
788
      {
 
789
        PrepareXmlCell(child, context);
 
790
      }
 
791
    }
 
792
    else if (name == wxT("small"))
 
793
    {
 
794
      // --- Small font size
 
795
      static double ratio = 2./3.;
 
796
      double currentSize = GetFontSize();
 
797
      SelectFont(wxT(""), wxT(""), currentSize * ratio, false);
 
798
      double delta = (currentSize - GetFontSize()) * 0.5 * ratio / GetScaleFactor();
 
799
      SetXY(GetX(), GetY() + delta);
 
800
      PrepareXmlCell(child, context);
 
801
      SetXY(GetX(), GetY() - delta);
 
802
      SelectFont(wxT(""), wxT(""), currentSize, false);
 
803
    }
 
804
    else if (name == wxT("sup"))
 
805
    {
 
806
      // --- Superscript
 
807
      static double ratio = 2./3.;
 
808
      double currentSize = GetFontSize();
 
809
      SelectFont(wxT(""), wxT(""), currentSize * ratio, false);
 
810
      double delta = (currentSize - GetFontSize()) * ratio / GetScaleFactor();
 
811
      SetXY(GetX(), GetY() - delta);
 
812
      PrepareXmlCell(child, context);
 
813
      SetXY(GetX(), GetY() + delta);
 
814
      SelectFont(wxT(""), wxT(""), currentSize, false);
 
815
    }
 
816
    else if (name == wxT("sub"))
 
817
    {
 
818
      // --- Subscript
 
819
      static double ratio = 2./3.;
 
820
      double currentSize = GetFontSize();
 
821
      SelectFont(wxT(""), wxT(""), currentSize * ratio, false);
 
822
      double delta = (currentSize - GetFontSize()) * ratio / GetScaleFactor();
 
823
      SetXY(GetX(), GetY() + delta);
 
824
      PrepareXmlCell(child, context);
 
825
      SetXY(GetX(), GetY() - delta);
 
826
      SelectFont(wxT(""), wxT(""), currentSize, false);
 
827
    }
 
828
    else if (name == wxT("ul"))
 
829
    {
 
830
      // --- Unordered list
 
831
      double leftMargin = GetLeftMargin();
 
832
      double indent = GetFontSize() / GetScaleFactor();
 
833
      SetLeftMargin(leftMargin + indent);
 
834
      wxXmlNode *listChild = child->GetChildren();
 
835
      while (listChild)
 
836
      {
 
837
        if ((listChild->GetName()).Lower() == wxT("li"))
 
838
        {
 
839
          Ln();
 
840
          newContext = new wxPdfCellContext(context.GetMaxWidth(), wxPDF_ALIGN_LEFT);
 
841
          //# newContext->AddHeight(GetLineHeight());
 
842
          context.AppendContext(newContext);
 
843
          PrepareXmlCell(listChild, *newContext);
 
844
          context.AddHeight(newContext->GetHeight());
 
845
          Ln();
 
846
        }
 
847
        listChild = listChild->GetNext();
 
848
      }
 
849
      SetLeftMargin(leftMargin);
 
850
    }
 
851
    else if (name == wxT("ol"))
 
852
    {
 
853
      // --- Ordered list
 
854
      double leftMargin = GetLeftMargin();
 
855
      double indent = GetStringWidth(wxT(" 00. "));
 
856
      wxString type = GetXmlAttribute(child, wxT("type"), wxT("1"));
 
857
      if (type.Length() > 0)
 
858
      {
 
859
        if (type[0] == wxT('a'))      
 
860
          indent = GetStringWidth(wxT(" xx. "));
 
861
        else if (type[0] == wxT('A')) 
 
862
          indent = GetStringWidth(wxT(" XX. "));
 
863
        else if (type[0] == wxT('i')) 
 
864
          indent = GetStringWidth(wxT(" xxx. "));
 
865
        else if (type[0] == wxT('I')) 
 
866
          indent = GetStringWidth(wxT(" XXX. "));
 
867
        else if (type[0] == wxT('z') && 
 
868
                 type.Length() > 1 && type[1] >= wxT('1') && type[1] <= wxT('4'))
 
869
          indent = 1.1 * GetFontSize() / GetScaleFactor();
 
870
      }
 
871
      SetLeftMargin(leftMargin + indent);
 
872
      wxXmlNode *listChild = child->GetChildren();
 
873
      while (listChild)
 
874
      {
 
875
        if ((listChild->GetName()).Lower() == wxT("li"))
 
876
        {
 
877
          Ln();
 
878
          newContext = new wxPdfCellContext(context.GetMaxWidth(), wxPDF_ALIGN_LEFT);
 
879
          //# newContext->AddHeight(GetLineHeight());
 
880
          context.AppendContext(newContext);
 
881
          PrepareXmlCell(listChild, *newContext);
 
882
          context.AddHeight(newContext->GetHeight());
 
883
          Ln();
 
884
        }
 
885
        listChild = listChild->GetNext();
 
886
      }
 
887
      SetLeftMargin(leftMargin);
 
888
    }
 
889
    else if (name == wxT("br"))
 
890
    {
 
891
      // --- Line break
 
892
      Ln();
 
893
      //# context.AddHeight(GetLineHeight());
 
894
      context.MarkLastLine();
 
895
      context.AddLine();
 
896
    }
 
897
    else if (name == wxT("p"))
 
898
    {
 
899
      // --- Paragraph
 
900
      wxString align = GetXmlAttribute(child, wxT("align"), wxT("left")).Lower();
 
901
      wxPdfAlignment alignment = wxPDF_ALIGN_LEFT;
 
902
      if (align == wxT("right"))        alignment = wxPDF_ALIGN_RIGHT;
 
903
      else if (align == wxT("center"))  alignment = wxPDF_ALIGN_CENTER;
 
904
      else if (align == wxT("justify")) alignment = wxPDF_ALIGN_JUSTIFY;
 
905
 
 
906
      Ln();
 
907
      newContext = new wxPdfCellContext(context.GetMaxWidth(), alignment);
 
908
      context.AppendContext(newContext);
 
909
      PrepareXmlCell(child, *newContext);
 
910
      newContext->MarkLastLine();
 
911
      context.AddHeight(newContext->GetHeight()+GetLineHeight());
 
912
      Ln();
 
913
      Ln();
 
914
    }
 
915
    else if (name == wxT("hr"))
 
916
    {
 
917
      // --- Horizontal rule
 
918
//      double hrWidth = GetPageWidth() - GetLeftMargin() - GetRightMargin();
 
919
//      long widthAttr;
 
920
      Ln();
 
921
//      wxString strWidth = child->GetPropVal(wxT("width"), wxT(""));
 
922
//      if (strWidth.Length() > 0 && strWidth.ToLong(&widthAttr))
 
923
//      {
 
924
//        hrWidth = hrWidth * 0.01 * widthAttr;
 
925
//      }
 
926
//      double x = GetX();
 
927
//      double y = GetY();
 
928
//      double wLine = GetLineWidth();
 
929
//      SetLineWidth(0.2);
 
930
//      Line(x, y, x + hrWidth, y);
 
931
//      SetLineWidth(wLine);
 
932
//      Ln();
 
933
      context.AddHeight(GetLineHeight());
 
934
      //context.AddLine();
 
935
    }
 
936
    else if (name == wxT("a"))
 
937
    {
 
938
      // --- Anchor
 
939
      PrepareXmlCell(child, context);
 
940
    }
 
941
    else if (name == wxT("img"))
 
942
    {
 
943
      // --- Image
 
944
      wxString src = GetXmlAttribute(child, wxT("src"), wxT(""));
 
945
      if (src.Length() > 0)
 
946
      { 
 
947
//        long width;
 
948
        long height;
 
949
//        wxString strWidth = child->GetPropVal(wxT("width"), wxT("0"));
 
950
        wxString strHeight = GetXmlAttribute(child, wxT("height"), wxT("0"));
 
951
//        if (!strWidth.ToLong(&width)) width = 0;
 
952
        if (!strHeight.ToLong(&height)) height = 0;
 
953
        double h = ((double) height) / (GetImageScale() * GetScaleFactor());
 
954
        // TODO: handle image
 
955
        // line height, position, margins etc.
 
956
        context.AddHeight(h);
 
957
      }
 
958
    }
 
959
    else if (name == wxT("span"))
 
960
    {
 
961
      PrepareXmlCell(child, context);
 
962
    }
 
963
    else if (name == wxT("font"))
 
964
    {
 
965
      // --- Font
 
966
      wxString    saveFamily = GetFontFamily();
 
967
      wxString    saveStyle  = GetFontStyle();
 
968
      double      saveSize   = GetFontSize();
 
969
      wxString strFace  = GetXmlAttribute(child, wxT("face"), wxT(""));
 
970
      double size = 0;
 
971
      wxString strSize  = GetXmlAttribute(child, wxT("size"), wxT(""));
 
972
      if (strSize.Length() > 0)
 
973
      {
 
974
        size = wxPdfUtility::String2Double(strSize);
 
975
      }
 
976
      if (size <= 0) size = saveSize;
 
977
      SelectFont(strFace, saveStyle, size, false);
 
978
      PrepareXmlCell(child, context);
 
979
      SelectFont(saveFamily, saveStyle, saveSize, false);
 
980
    }
 
981
    else if (name == wxT("code"))
 
982
    {
 
983
      // --- Code section
 
984
      wxString    saveFamily = GetFontFamily();
 
985
      wxString    saveStyle  = GetFontStyle();
 
986
      double      saveSize   = GetFontSize();
 
987
      wxString strFace  = GetXmlAttribute(child, wxT("face"), wxT("courier"));
 
988
      double size = 0;
 
989
      wxString strSize  = GetXmlAttribute(child, wxT("size"), wxT("10"));
 
990
      if (strSize.Length() > 0)
 
991
      {
 
992
        size = wxPdfUtility::String2Double(strSize);
 
993
      }
 
994
      if (size <= 0) size = saveSize;
 
995
      SelectFont(strFace, wxT(""), size, false);
 
996
      Ln();
 
997
      context.MarkLastLine();
 
998
      context.AddLine();
 
999
      PrepareXmlCell(child, context);
 
1000
      Ln();
 
1001
      SelectFont(saveFamily, saveStyle, saveSize, false);
 
1002
    }
 
1003
    else if (name == wxT("h1") || name == wxT("h2") || name == wxT("h3") || 
 
1004
             name == wxT("h4") || name == wxT("h5") || name == wxT("h6"))
 
1005
    {
 
1006
      // --- Header
 
1007
      wxString align = GetXmlAttribute(child, wxT("align"), wxT("left")).Lower();
 
1008
      wxPdfAlignment alignment = wxPDF_ALIGN_LEFT;
 
1009
      if (align == wxT("right"))        alignment = wxPDF_ALIGN_RIGHT;
 
1010
      else if (align == wxT("center"))  alignment = wxPDF_ALIGN_CENTER;
 
1011
      else if (align == wxT("justify")) alignment = wxPDF_ALIGN_JUSTIFY;
 
1012
 
 
1013
      if (context.GetLastLineWidth() > 0)
 
1014
      {
 
1015
        Ln();
 
1016
      }
 
1017
      Ln();
 
1018
      context.AddHeight(GetLineHeight());
 
1019
      newContext = new wxPdfCellContext(context.GetMaxWidth(), alignment);
 
1020
      context.AppendContext(newContext);
 
1021
 
 
1022
      double headsize = (wxT('4') - name[1]) * 2;
 
1023
      double currentFontSize = GetFontSize();
 
1024
      SelectFont(wxT(""), wxT(""), currentFontSize + headsize, false);
 
1025
      wxString addStyle = wxT("B");
 
1026
      wxString style = GetFontStyle();
 
1027
      if (!style.Contains(addStyle))
 
1028
      {
 
1029
        SelectFont(wxT(""), style + addStyle, 0, false);
 
1030
        PrepareXmlCell(child, *newContext);
 
1031
        SelectFont(wxT(""), style, 0, false);
 
1032
      }
 
1033
      else
 
1034
      {
 
1035
        PrepareXmlCell(child, *newContext);
 
1036
      }
 
1037
      context.AddHeight(newContext->GetHeight());
 
1038
      // reset
 
1039
      SelectFont(wxT(""), wxT(""), currentFontSize, false);
 
1040
      Ln();
 
1041
    }
 
1042
    else if (name == wxT("table"))
 
1043
    {
 
1044
      // --- Table
 
1045
      wxString border = GetXmlAttribute(child, wxT("border"), wxT("0")).Lower();
 
1046
      bool hasBorder = (border != wxT("0"));
 
1047
      wxString align = GetXmlAttribute(child, wxT("align"), wxT("")).Lower();
 
1048
      wxPdfAlignment hAlignment = context.GetHAlign();
 
1049
      if (align == wxT("right"))        hAlignment = wxPDF_ALIGN_RIGHT;
 
1050
      else if (align == wxT("center"))  hAlignment = wxPDF_ALIGN_CENTER;
 
1051
      else if (align == wxT("justify")) hAlignment = wxPDF_ALIGN_JUSTIFY;
 
1052
      align = GetXmlAttribute(child, wxT("valign"), wxT("top")).Lower();
 
1053
      wxPdfAlignment vAlignment = wxPDF_ALIGN_TOP;
 
1054
      if (align == wxT("bottom"))      vAlignment = wxPDF_ALIGN_BOTTOM;
 
1055
      else if (align == wxT("middle")) vAlignment = wxPDF_ALIGN_MIDDLE;
 
1056
      else if (align == wxT("center")) vAlignment = wxPDF_ALIGN_MIDDLE;
 
1057
      double pad = 1.5 / GetScaleFactor();
 
1058
      wxString padding = GetXmlAttribute(child, wxT("cellpadding"), wxT("")).Lower();
 
1059
      if (padding.Length() > 0)
 
1060
      {
 
1061
        pad = wxPdfUtility::String2Double(padding);
 
1062
        if (pad < 0) pad = 0;
 
1063
      }
 
1064
 
 
1065
      wxPdfTable* table = new wxPdfTable(this);
 
1066
      table->SetPad(pad);
 
1067
      table->SetBorder(hasBorder);
 
1068
      newContext = new wxPdfCellContext(context.GetMaxWidth(), hAlignment, vAlignment);
 
1069
      context.AppendContext(newContext);
 
1070
      newContext->SetTable(table);
 
1071
      PrepareXmlTable(child, *newContext);
 
1072
      context.AddHeight(newContext->GetHeight());
 
1073
    }
 
1074
    else
 
1075
    {
 
1076
      // --- Content
 
1077
      if (child->GetType() == wxXML_TEXT_NODE || name == wxT("msg"))
 
1078
      {
 
1079
        if (context.GetLastLineWidth() == 0)
 
1080
        {
 
1081
          context.AddHeight(GetLineHeight());
 
1082
        }
 
1083
        double wmax = context.GetMaxWidth()-context.GetLastLineWidth();
 
1084
        wxString s;
 
1085
        if (name == wxT("msg"))
 
1086
        {
 
1087
          s = GetNodeContent(child);
 
1088
          if (m_translate) s = wxGetTranslation(s);
 
1089
         }
 
1090
        else
 
1091
        {
 
1092
          s = child->GetContent();
 
1093
        }
 
1094
        s.Replace(wxT("\r"),wxT("")); // remove carriage returns
 
1095
        int nb = (int) s.Length();
 
1096
        if (nb > 0 && s[nb-1] == wxT('\n'))
 
1097
        {
 
1098
          --nb;
 
1099
        }
 
1100
        int sep = -1;
 
1101
        int i = 0;
 
1102
        int j = 0;
 
1103
        double len = 0;
 
1104
        double ls = 0;
 
1105
        int ns = 0;
 
1106
        int nl = 1;
 
1107
        wxChar c = 0;
 
1108
        while (i < nb)
 
1109
        {
 
1110
          // Get next character
 
1111
          c = s[i];
 
1112
          if (c == wxT('\n'))
 
1113
          {
 
1114
            // Explicit line break
 
1115
            i++;
 
1116
            context.AddLastLineValues(len, ns);
 
1117
            sep = -1;
 
1118
            j = i;
 
1119
            len = 0;
 
1120
            ns = 0;
 
1121
            nl++;
 
1122
            context.MarkLastLine();
 
1123
            context.AddLine();
 
1124
            context.AddHeight(GetLineHeight());
 
1125
            wmax = context.GetMaxWidth();
 
1126
            continue;
 
1127
          }
 
1128
          if (c == wxT(' '))
 
1129
          {
 
1130
            sep = i;
 
1131
            ls = len;
 
1132
            ns++;
 
1133
          }
 
1134
          double lastlen = len;
 
1135
          len = GetStringWidth(s.SubString(j, i));
 
1136
 
 
1137
          if (len > wmax)
 
1138
          {
 
1139
            // Automatic line break
 
1140
            if (sep == -1)
 
1141
            {
 
1142
              ls = lastlen;
 
1143
              if (context.GetLastLineWidth() > 0)
 
1144
              {
 
1145
                if (context.GetLastChar() == wxT(' '))
 
1146
                {
 
1147
                  context.AddLastLineValues(-context.GetLastSpaceWidth(), -1);
 
1148
                }
 
1149
                i = j;
 
1150
              }
 
1151
              else
 
1152
              {
 
1153
                if (i == j)
 
1154
                {
 
1155
                  i++;
 
1156
                }
 
1157
              }
 
1158
            }
 
1159
            else
 
1160
            {
 
1161
              i = sep + 1;
 
1162
              ns--;
 
1163
            }
 
1164
            context.AddLastLineValues(ls, ns);
 
1165
            sep = -1;
 
1166
            j = i;
 
1167
            len = 0;
 
1168
            ns = 0;
 
1169
            nl++;
 
1170
            context.AddLine();
 
1171
            context.AddHeight(GetLineHeight());
 
1172
            wmax = context.GetMaxWidth();
 
1173
          }
 
1174
          else
 
1175
          {
 
1176
            i++;
 
1177
          }
 
1178
        }
 
1179
        // Last chunk
 
1180
        context.AddLastLineValues(len, ns);
 
1181
        context.SetLastChar(c);
 
1182
        context.SetLastSpaceWidth(GetStringWidth(wxT(" ")));
 
1183
      }
 
1184
    }
 
1185
    child = child->GetNext();
 
1186
  }
 
1187
}
 
1188
 
 
1189
void
 
1190
wxPdfDocument::WriteXml(const wxString& xmlString)
 
1191
{
 
1192
  if (GetLineHeight() == 0)
 
1193
  {
 
1194
    SetLineHeight(GetFontSize()*1.25 / GetScaleFactor());
 
1195
  }
 
1196
  wxString xmlStringWithXmlRoot(wxT("<xml>")+xmlString+wxT("</xml>"));          
 
1197
  wxStringInputStream xmlStream(xmlStringWithXmlRoot);
 
1198
  wxXmlDocument xmlDocument;
 
1199
  bool loaded = xmlDocument.Load(xmlStream);
 
1200
  if (loaded)
 
1201
  {
 
1202
    if (xmlDocument.IsOk())
 
1203
    {
 
1204
      wxXmlNode* root = xmlDocument.GetRoot();
 
1205
      double maxWidth = GetPageWidth() - GetRightMargin() - GetX();
 
1206
      wxPdfCellContext context(maxWidth, wxPDF_ALIGN_LEFT);
 
1207
      double saveX = GetX();
 
1208
      double saveY = GetY();
 
1209
      PrepareXmlCell(root, context);
 
1210
      SetXY(saveX, saveY);
 
1211
      WriteXmlCell(root, context);
 
1212
    }
 
1213
    else
 
1214
    {
 
1215
      wxLogDebug(wxString(wxT("wxPdfDocument::WriteXml: ")) +
 
1216
                 wxString(_("Markup invalid.")));
 
1217
      return /* false */;
 
1218
    }
 
1219
  }
 
1220
  else
 
1221
  {
 
1222
    // TODO: Error handling
 
1223
    wxLogDebug(wxString(wxT("wxPdfDocument::WriteXml: ")) +
 
1224
               wxString(_("Unable to load markup string.")));
 
1225
  }
 
1226
}
 
1227
 
 
1228
void
 
1229
wxPdfDocument::WriteXml(wxXmlNode* node)
 
1230
{
 
1231
  if (GetLineHeight() == 0)
 
1232
  {
 
1233
    SetLineHeight(GetFontSize()*1.25 / GetScaleFactor());
 
1234
  }
 
1235
  double maxWidth = GetPageWidth() - GetRightMargin() - GetX();
 
1236
  wxPdfCellContext context(maxWidth, wxPDF_ALIGN_LEFT);
 
1237
  double saveX = GetX();
 
1238
  double saveY = GetY();
 
1239
  PrepareXmlCell(node, context);
 
1240
  SetXY(saveX, saveY);
 
1241
  WriteXmlCell(node, context);
 
1242
}
 
1243
 
 
1244
void
 
1245
wxPdfDocument::WriteXmlCell(wxXmlNode* node, wxPdfCellContext& context)
 
1246
{
 
1247
  wxPdfCellContext* newContext;
 
1248
  wxXmlNode *child = node->GetChildren();
 
1249
  while (child)
 
1250
  {
 
1251
    wxString name = (child->GetName()).Lower();
 
1252
    // parse the children
 
1253
 
 
1254
    if (name == wxT("b") || name == wxT("i") || name == wxT("u") ||
 
1255
        name == wxT("o") || name == wxT("s") ||
 
1256
        name == wxT("strong") || name == wxT("em"))
 
1257
    {
 
1258
      // --- Bold, Italic, Underline, Overline, Strikeout
 
1259
      // --- Strong (= bold), Emphasize (= italic)
 
1260
      wxString addStyle = name.Upper();
 
1261
      if (name.Length() > 1)
 
1262
      {
 
1263
        if (name == wxT("strong"))  addStyle = wxT("B");
 
1264
        else if (name == wxT("em")) addStyle = wxT("I");
 
1265
      }
 
1266
      wxString style = GetFontStyle();
 
1267
      if (!style.Contains(addStyle))
 
1268
      {
 
1269
        SetFont(wxT(""), style + addStyle);
 
1270
        WriteXmlCell(child, context);
 
1271
        SetFont(wxT(""), style);
 
1272
      }
 
1273
      else
 
1274
      {
 
1275
        WriteXmlCell(child, context);
 
1276
      }
 
1277
    }
 
1278
    else if (name == wxT("small"))
 
1279
    {
 
1280
      // --- Small font
 
1281
      static double ratio = 2./3.;
 
1282
      double currentSize = GetFontSize();
 
1283
      SetFontSize(currentSize * ratio);
 
1284
      double delta = (currentSize - GetFontSize()) * 0.5 * ratio / GetScaleFactor();
 
1285
      SetXY(GetX(), GetY() + delta);
 
1286
      WriteXmlCell(child, context);
 
1287
      SetXY(GetX(), GetY() - delta);
 
1288
      SetFontSize(currentSize);
 
1289
    }
 
1290
    else if (name == wxT("sup"))
 
1291
    {
 
1292
      // --- Superscript
 
1293
      static double ratio = 2./3.;
 
1294
      double currentSize = GetFontSize();
 
1295
      SetFontSize(currentSize * ratio);
 
1296
      double delta = (currentSize - GetFontSize()) * ratio / GetScaleFactor();
 
1297
      SetXY(GetX(), GetY() - delta);
 
1298
      WriteXmlCell(child, context);
 
1299
      SetXY(GetX(), GetY() + delta);
 
1300
      SetFontSize(currentSize);
 
1301
    }
 
1302
    else if (name == wxT("sub"))
 
1303
    {
 
1304
      // --- Subscript
 
1305
      static double ratio = 2./3.;
 
1306
      double currentSize = GetFontSize();
 
1307
      SetFontSize(currentSize * ratio);
 
1308
      double delta = (currentSize - GetFontSize()) * ratio / GetScaleFactor();
 
1309
      SetXY(GetX(), GetY() + delta);
 
1310
      WriteXmlCell(child, context);
 
1311
      SetXY(GetX(), GetY() - delta);
 
1312
      SetFontSize(currentSize);
 
1313
    }
 
1314
    else if (name == wxT("ul"))
 
1315
    {
 
1316
      // --- Unordered list
 
1317
#if wxUSE_UNICODE
 
1318
      static wxChar bulletChar = 0x2022;
 
1319
      static wxChar dashChar   = 0x2013;
 
1320
#else
 
1321
      static wxChar bulletChar = '\x95'; // dec 149
 
1322
      static wxChar dashChar   = '\x96'; // dec 150
 
1323
#endif
 
1324
      wxChar itemChar = bulletChar;
 
1325
      bool useZapfDingBats = false;
 
1326
      long zapfChar = 0;
 
1327
      wxString type = GetXmlAttribute(child, wxT("type"), wxT("bullet"));
 
1328
 
 
1329
      if (type.IsNumber() && type.ToLong(&zapfChar))
 
1330
      {
 
1331
        if (zapfChar >= 0 && zapfChar <= 255)
 
1332
        {
 
1333
          itemChar = zapfChar;
 
1334
          useZapfDingBats = true;
 
1335
        }
 
1336
      }
 
1337
      else if (type.Lower() == wxT("dash"))
 
1338
      {
 
1339
        itemChar = dashChar;
 
1340
      }
 
1341
      double leftMargin = GetLeftMargin();
 
1342
      double indent = GetFontSize() / GetScaleFactor();
 
1343
      SetLeftMargin(leftMargin + indent);
 
1344
      wxXmlNode *listChild = child->GetChildren();
 
1345
      while (listChild)
 
1346
      {
 
1347
        if ((listChild->GetName()).Lower() == wxT("li"))
 
1348
        {
 
1349
          wxString saveFont = GetFontFamily();
 
1350
          wxString saveStyle = GetFontStyle();
 
1351
          double saveSize = GetFontSize();
 
1352
          if (useZapfDingBats)
 
1353
          {
 
1354
            SetFont(wxT("zapfdingbats"), wxT(""), 0.7*saveSize);
 
1355
          }
 
1356
          else
 
1357
          {
 
1358
            SetFont(wxT("Helvetica"), wxT(""), saveSize);
 
1359
          }
 
1360
          SetLeftMargin(leftMargin);
 
1361
          SetXY(leftMargin, GetY());
 
1362
          WriteCell(GetLineHeight(), wxString(itemChar));
 
1363
          SetLeftMargin(leftMargin+indent);
 
1364
          SetXY(leftMargin+indent, GetY()); 
 
1365
          SetFont(saveFont, saveStyle, saveSize);
 
1366
          //Ln();
 
1367
          newContext = context.GetCurrentContext();
 
1368
          context.IncrementCurrentContext();
 
1369
          WriteXmlCell(listChild, *newContext);
 
1370
          Ln();
 
1371
        }
 
1372
        listChild = listChild->GetNext();
 
1373
      }
 
1374
      SetLeftMargin(leftMargin);
 
1375
      SetXY(leftMargin, GetY());
 
1376
    }
 
1377
    else if (name == wxT("ol"))
 
1378
    {
 
1379
      // --- Ordered list
 
1380
      bool useZapfDingBats = false;
 
1381
      int listCount = 0;
 
1382
      int listType = 1;
 
1383
      int listCycle = 0;
 
1384
      long listStart;
 
1385
      wxString start = GetXmlAttribute(child, wxT("start"), wxT("1"));
 
1386
      if (start.IsNumber() && start.ToLong(&listStart))
 
1387
      {
 
1388
        listCount += (listStart - 1);
 
1389
      }
 
1390
      double indent = GetStringWidth(wxT(" 00. "));
 
1391
      wxString type = GetXmlAttribute(child, wxT("type"), wxT("1"));
 
1392
      if (type.Length() > 0)
 
1393
      {
 
1394
        if (type[0] == wxT('1'))
 
1395
        {
 
1396
          listType = 1;
 
1397
        }
 
1398
        else if (type[0] == wxT('a'))
 
1399
        {
 
1400
          listType = 2;
 
1401
          listCycle = 26;
 
1402
          indent = GetStringWidth(wxT(" xx. "));
 
1403
        }
 
1404
        else if (type[0] == wxT('A'))
 
1405
        {
 
1406
          listType = 3;
 
1407
          listCycle = 26;
 
1408
          indent = GetStringWidth(wxT(" XX. "));
 
1409
        }
 
1410
        else if (type[0] == wxT('i'))
 
1411
        {
 
1412
          listType = 4;
 
1413
          indent = GetStringWidth(wxT(" xxx. "));
 
1414
        }
 
1415
        else if (type[0] == wxT('I'))
 
1416
        {
 
1417
          listType = 5;
 
1418
          indent = GetStringWidth(wxT(" XXX. "));
 
1419
        }
 
1420
        else if (type[0] == wxT('z'))
 
1421
        {
 
1422
          if (type.Length() > 1 && type[1] >= wxT('1') && type[1] <= wxT('4'))
 
1423
          {
 
1424
            useZapfDingBats = true;
 
1425
            listType = type[1] - wxT('1');
 
1426
            listCycle = 10;
 
1427
            indent = 1.1 * GetFontSize() / GetScaleFactor();
 
1428
          }
 
1429
        }
 
1430
      }
 
1431
      double leftMargin = GetLeftMargin();
 
1432
      SetLeftMargin(leftMargin + indent);
 
1433
      Ln();
 
1434
      wxXmlNode *listChild = child->GetChildren();
 
1435
      while (listChild)
 
1436
      {
 
1437
        if ((listChild->GetName()).Lower() == wxT("li"))
 
1438
        {
 
1439
          wxString saveFont = GetFontFamily();
 
1440
          wxString saveStyle = GetFontStyle();
 
1441
          double saveSize = GetFontSize();
 
1442
          SetLeftMargin(leftMargin);
 
1443
          SetXY(leftMargin, GetY());
 
1444
          if (useZapfDingBats)
 
1445
          {
 
1446
            SetFont(wxT("zapfdingbats"), wxT(""), 0.85*saveSize);
 
1447
            wxChar itemChar = 172 + 10 * listType + listCount % listCycle;
 
1448
            WriteCell(GetLineHeight(), wxString(itemChar));
 
1449
          }
 
1450
          else
 
1451
          {
 
1452
            wxChar itemChar;
 
1453
            SetFont(wxT("Helvetica"), wxT(""), saveSize);
 
1454
            wxString item;
 
1455
            switch (listType)
 
1456
            {
 
1457
              case 2:
 
1458
                itemChar = wxT('a') + listCount % listCycle;
 
1459
                item = wxString(itemChar) + wxT(". ");
 
1460
                break;
 
1461
              case 3:
 
1462
                itemChar = wxT('A') + listCount % listCycle;
 
1463
                item = wxString(itemChar) + wxT(". ");
 
1464
                break;
 
1465
              case 4:
 
1466
                item = wxPdfUtility::Convert2Roman(listCount+1).Lower() + wxT(". ");
 
1467
                break;
 
1468
              case 5:
 
1469
                item = wxPdfUtility::Convert2Roman(listCount+1) + wxT(". ");
 
1470
                break;
 
1471
              case 1:
 
1472
              default:
 
1473
                item = wxString::Format(wxT("%d. "), listCount+1);
 
1474
                break;
 
1475
            }
 
1476
            Cell(indent, GetLineHeight(), item, wxPDF_BORDER_NONE, 0, wxPDF_ALIGN_RIGHT);
 
1477
          }
 
1478
 
 
1479
          SetLeftMargin(leftMargin+indent);
 
1480
          SetXY(leftMargin+indent, GetY()); 
 
1481
          SetFont(saveFont, saveStyle, saveSize);
 
1482
          listCount++;
 
1483
          newContext = context.GetCurrentContext();
 
1484
          context.IncrementCurrentContext();
 
1485
          WriteXmlCell(listChild, *newContext);
 
1486
          Ln();
 
1487
        }
 
1488
        listChild = listChild->GetNext();
 
1489
      }
 
1490
      SetLeftMargin(leftMargin);
 
1491
      SetXY(leftMargin, GetY());
 
1492
    }
 
1493
    else if (name == wxT("br"))
 
1494
    {
 
1495
      // --- Line break
 
1496
      Ln();
 
1497
      context.IncrementCurrentLine();
 
1498
    }
 
1499
    else if (name == wxT("p"))
 
1500
    {
 
1501
      // --- Paragraph
 
1502
      if (GetX() > GetLeftMargin())
 
1503
      {
 
1504
        Ln();
 
1505
      }
 
1506
      newContext = context.GetCurrentContext();
 
1507
      context.IncrementCurrentContext();
 
1508
      WriteXmlCell(child, *newContext);
 
1509
      if (GetX() > GetLeftMargin())
 
1510
      {
 
1511
        Ln();
 
1512
      }
 
1513
      Ln();
 
1514
    }
 
1515
    else if (name == wxT("hr"))
 
1516
    {
 
1517
      // --- Horizontal rule
 
1518
      double hrWidth = GetPageWidth() - GetLeftMargin() - GetRightMargin();
 
1519
      long widthAttr;
 
1520
      Ln();
 
1521
      wxString strWidth = GetXmlAttribute(child, wxT("width"), wxT(""));
 
1522
      if (strWidth.Length() > 0 && strWidth.ToLong(&widthAttr))
 
1523
      {
 
1524
        hrWidth = hrWidth * 0.01 * widthAttr;
 
1525
      }
 
1526
      double x = GetX();
 
1527
      double y = GetY();
 
1528
      double wLine = GetLineWidth();
 
1529
      SetLineWidth(0.2);
 
1530
      Line(x, y, x + hrWidth, y);
 
1531
      SetLineWidth(wLine);
 
1532
      Ln();
 
1533
    }
 
1534
    else if (name == wxT("a"))
 
1535
    {
 
1536
      // --- Anchor
 
1537
      wxString href = GetXmlAttribute(child, wxT("href"), wxT(""));
 
1538
      wxString nameAttr = GetXmlAttribute(child, wxT("name"), wxT(""));
 
1539
      if (href.Length() > 0)
 
1540
      {
 
1541
        if (href[0] == wxT('#'))
 
1542
        {
 
1543
          nameAttr = href.Right(href.Length()-1);
 
1544
          if (nameAttr.Length() > 0)
 
1545
          {
 
1546
            if (m_namedLinks->find(nameAttr) == m_namedLinks->end())
 
1547
            {
 
1548
              (*m_namedLinks)[nameAttr] = AddLink();
 
1549
            }
 
1550
          }
 
1551
        }
 
1552
        context.SetHRef(href);
 
1553
        wxPdfColour saveColour = GetTextColour();
 
1554
        SetTextColour(0, 0, 255);
 
1555
        wxString style = GetFontStyle();
 
1556
        if (!style.Contains(wxT("U")))
 
1557
        {
 
1558
          SetFont(wxT(""), style + wxT("U"));
 
1559
          WriteXmlCell(child, context);
 
1560
          SetFont(wxT(""), style);
 
1561
        }
 
1562
        else
 
1563
        {
 
1564
          WriteXmlCell(child, context);
 
1565
        }
 
1566
        SetTextColour(saveColour);
 
1567
        context.SetHRef(wxT(""));
 
1568
      }
 
1569
      else if (nameAttr.Length() > 0)
 
1570
      { 
 
1571
        int link;
 
1572
        if (m_namedLinks->find(nameAttr) == m_namedLinks->end())
 
1573
        {
 
1574
          link = AddLink();
 
1575
          (*m_namedLinks)[nameAttr] = link;
 
1576
        }
 
1577
        else
 
1578
        {
 
1579
          link = (*m_namedLinks)[nameAttr];
 
1580
        }
 
1581
        SetLink(link, -1, -1);
 
1582
        WriteXmlCell(child, context);        
 
1583
      }
 
1584
      else
 
1585
      {
 
1586
        WriteXmlCell(child, context);
 
1587
      }
 
1588
    }
 
1589
    else if (name == wxT("img"))
 
1590
    {
 
1591
      // --- Image
 
1592
      wxString src = GetXmlAttribute(child, wxT("src"), wxT(""));
 
1593
      if (src.Length() > 0)
 
1594
      { 
 
1595
        long width;
 
1596
        long height;
 
1597
        wxString strWidth = GetXmlAttribute(child, wxT("width"), wxT("0"));
 
1598
        wxString strHeight = GetXmlAttribute(child, wxT("height"), wxT("0"));
 
1599
        if (!strWidth.ToLong(&width)) width = 0;
 
1600
        if (!strHeight.ToLong(&height)) height = 0;
 
1601
        double x = GetX();
 
1602
        double y = GetY();
 
1603
        double w = ((double) width) / (GetImageScale() * GetScaleFactor());
 
1604
        double h = ((double) height) / (GetImageScale() * GetScaleFactor());
 
1605
        wxString align = GetXmlAttribute(child, wxT("align"), wxT("left")).Lower();
 
1606
        double delta;
 
1607
        if (align == wxT("right"))
 
1608
        {
 
1609
          delta = context.GetMaxWidth() - w;
 
1610
        }
 
1611
        else if (align == wxT("center"))
 
1612
        {
 
1613
          delta = 0.5 * (context.GetMaxWidth() - w);
 
1614
        }
 
1615
        else
 
1616
        {
 
1617
          delta = 0;
 
1618
        }
 
1619
        // line height, position, margins etc.
 
1620
        if (GetX() > GetLeftMargin())
 
1621
        {
 
1622
          Ln();
 
1623
        }
 
1624
        Image(src, x+delta, y, w, h);
 
1625
        SetXY(x, y+h);
 
1626
      }
 
1627
    }
 
1628
    else if (name == wxT("span"))
 
1629
    {
 
1630
      int saveFillStyle = context.GetFillStyle();
 
1631
      wxPdfColour saveColor  = GetFillColour();
 
1632
      wxString strColor = GetXmlAttribute(child, wxT("color"), wxT(""));
 
1633
      if (strColor.Length() > 0)
 
1634
      {
 
1635
        SetFillColour(wxPdfColour(strColor));
 
1636
        context.SetFillStyle(1);
 
1637
      }
 
1638
      WriteXmlCell(child, context);
 
1639
      if (strColor.Length() > 0)
 
1640
      {
 
1641
        context.SetFillStyle(saveFillStyle);
 
1642
        SetFillColour(saveColor);
 
1643
      }
 
1644
    }
 
1645
    else if (name == wxT("font"))
 
1646
    {
 
1647
      // --- Font
 
1648
      wxString    saveFamily = GetFontFamily();
 
1649
      wxString    saveStyle  = GetFontStyle();
 
1650
      double      saveSize   = GetFontSize();
 
1651
      wxPdfColour saveColour = GetTextColour();
 
1652
      wxString strFace   = GetXmlAttribute(child, wxT("face"), wxT(""));
 
1653
      wxString strSize   = GetXmlAttribute(child, wxT("size"), wxT(""));
 
1654
      wxString strColour = GetXmlAttribute(child, wxT("color"), wxT(""));
 
1655
      double size = 0;
 
1656
      if (strSize.Length() > 0)
 
1657
      {
 
1658
        size = wxPdfUtility::String2Double(strSize);
 
1659
      }
 
1660
      if (size <= 0) size = saveSize;
 
1661
      SetFont(strFace, saveStyle, size);
 
1662
      if (strColour.Length() > 0)
 
1663
      {
 
1664
        SetTextColour(wxPdfColour(strColour));
 
1665
      }
 
1666
      WriteXmlCell(child, context);
 
1667
      if (strColour.Length() > 0)
 
1668
      {
 
1669
        SetTextColour(saveColour);
 
1670
      }
 
1671
      SetFont(saveFamily, saveStyle, saveSize);
 
1672
    }
 
1673
    else if (name == wxT("code"))
 
1674
    {
 
1675
      // --- Code section
 
1676
      wxString    saveFamily = GetFontFamily();
 
1677
      wxString    saveStyle  = GetFontStyle();
 
1678
      double      saveSize   = GetFontSize();
 
1679
      wxPdfColour saveColour  = GetTextColour();
 
1680
      wxString strFace  = GetXmlAttribute(child, wxT("face"), wxT("courier"));
 
1681
      wxString strSize  = GetXmlAttribute(child, wxT("size"), wxT("10"));
 
1682
      wxString strColour = GetXmlAttribute(child, wxT("color"), wxT(""));
 
1683
      double size = 0;
 
1684
      if (strSize.Length() > 0)
 
1685
      {
 
1686
        size = wxPdfUtility::String2Double(strSize);
 
1687
      }
 
1688
      if (size <= 0) size = saveSize;
 
1689
      SetFont(strFace, wxT(""), size);
 
1690
      if (strColour.Length() > 0)
 
1691
      {
 
1692
        SetTextColour(wxPdfColour(strColour));
 
1693
      }
 
1694
      Ln();
 
1695
      context.IncrementCurrentLine();
 
1696
      WriteXmlCell(child, context);
 
1697
      Ln();
 
1698
      if (strColour.Length() > 0)
 
1699
      {
 
1700
        SetTextColour(saveColour);
 
1701
      }
 
1702
      SetFont(saveFamily, saveStyle, saveSize);
 
1703
    }
 
1704
    else if (name == wxT("h1") || name == wxT("h2") || name == wxT("h3") || 
 
1705
             name == wxT("h4") || name == wxT("h5") || name == wxT("h6"))
 
1706
    {
 
1707
      // --- Header
 
1708
      newContext = context.GetCurrentContext();
 
1709
      context.IncrementCurrentContext();
 
1710
 
 
1711
      double headsize = (wxT('4') - name[1]) * 2;
 
1712
      double currentFontSize = GetFontSize();
 
1713
      if (GetX() > GetLeftMargin())
 
1714
      {
 
1715
        Ln();
 
1716
      }
 
1717
      Ln();
 
1718
      wxString addStyle = wxT("B");
 
1719
      wxString style = GetFontStyle();
 
1720
      if (!style.Contains(addStyle))
 
1721
      {
 
1722
        SetFont(wxT(""), style + addStyle, currentFontSize + headsize);
 
1723
        WriteXmlCell(child, *newContext);
 
1724
        SetFont(wxT(""), style, currentFontSize);
 
1725
      }
 
1726
      else
 
1727
      {
 
1728
        SetFontSize(currentFontSize + headsize);
 
1729
        WriteXmlCell(child, *newContext);
 
1730
        SetFontSize(currentFontSize);
 
1731
      }
 
1732
      Ln();
 
1733
    }
 
1734
    else if (name == wxT("table"))
 
1735
    {
 
1736
      // --- Table
 
1737
      newContext = context.GetCurrentContext();
 
1738
      context.IncrementCurrentContext();
 
1739
      WriteXmlTable(*newContext);
 
1740
    }
 
1741
    else
 
1742
    {
 
1743
      // --- Content
 
1744
      if (child->GetType() == wxXML_TEXT_NODE || name == wxT("msg"))
 
1745
      {
 
1746
        wxPdfLink link = wxPdfLink(-1);
 
1747
        wxString href = context.GetHRef();
 
1748
        if (href.Length() > 0)
 
1749
        {
 
1750
          if (href[0] == wxT('#'))
 
1751
          {
 
1752
            wxString nameAttr = href.Right(href.Length()-1);
 
1753
            if (nameAttr.Length() > 0)
 
1754
            {
 
1755
              if (m_namedLinks->find(nameAttr) != m_namedLinks->end())
 
1756
              {
 
1757
                link = wxPdfLink((*m_namedLinks)[nameAttr]);
 
1758
              }
 
1759
            }
 
1760
          }
 
1761
          else
 
1762
          {
 
1763
            link = wxPdfLink(href);
 
1764
          }
 
1765
        }
 
1766
 
 
1767
        double h = GetLineHeight();
 
1768
        double wmax = context.GetCurrentLineWidth() + wxPDF_EPSILON;
 
1769
        DoXmlAlign(context);
 
1770
 
 
1771
        wxString s;
 
1772
        if (name == wxT("msg"))
 
1773
        {
 
1774
          s = GetNodeContent(child);
 
1775
          if (m_translate) s = wxGetTranslation(s);
 
1776
        }
 
1777
        else
 
1778
        {
 
1779
          s = child->GetContent();
 
1780
        }
 
1781
        s.Replace(wxT("\r"),wxT("")); // remove carriage returns
 
1782
        int nb = (int) s.Length();
 
1783
        if (nb > 0 && s[nb-1] == wxT('\n'))
 
1784
        {
 
1785
          --nb;
 
1786
        }
 
1787
 
 
1788
        int sep = -1;
 
1789
        int i = 0;
 
1790
        int j = 0;
 
1791
        double len = 0;
 
1792
        int ns = 0;
 
1793
        int nl = 1;
 
1794
        wxChar c;
 
1795
        while (i < nb)
 
1796
        {
 
1797
          // Get next character
 
1798
          c = s[i];
 
1799
          if (c == wxT('\n'))
 
1800
          {
 
1801
            // Explicit line break
 
1802
            if (m_ws > 0)
 
1803
            {
 
1804
              m_ws = 0;
 
1805
              Out("0 Tw");
 
1806
            }
 
1807
            WriteCell(h,s.SubString(j,i-1), wxPDF_BORDER_NONE, context.GetFillStyle(), link);
 
1808
            i++;
 
1809
            sep = -1;
 
1810
            j = i;
 
1811
            len = 0;
 
1812
            ns = 0;
 
1813
            nl++;
 
1814
            context.IncrementCurrentLine();
 
1815
            Ln();
 
1816
            DoXmlAlign(context);
 
1817
            wmax = context.GetCurrentLineWidth();
 
1818
            continue;
 
1819
          }
 
1820
          if (c == wxT(' '))
 
1821
          {
 
1822
            sep = i;
 
1823
            ns++;
 
1824
          }
 
1825
          len = GetStringWidth(s.SubString(j, i));
 
1826
 
 
1827
          if (len > wmax)
 
1828
          {
 
1829
            // Automatic line break
 
1830
            if (sep == -1)
 
1831
            {
 
1832
              // Case 1: current line length exactly matches the maximum with
 
1833
              // Case 2: current line contains no spaces and line length plus epsilon exactly matches the maximum width
 
1834
              //         (line break in the middle of a word if the word is too long to fit on the line)
 
1835
              if (  wmax == context.GetCurrentLineWidth() || 
 
1836
                  ((wmax == context.GetCurrentLineWidth() + wxPDF_EPSILON) && context.GetCurrentLineSpaces() == 0))
 
1837
              {
 
1838
                if (i == j)
 
1839
                {
 
1840
                  i++;
 
1841
                }
 
1842
                WriteCell(h,s.SubString(j,i-1), wxPDF_BORDER_NONE, context.GetFillStyle(), link);
 
1843
              }
 
1844
              else
 
1845
              {
 
1846
                i = j;
 
1847
              }
 
1848
            }
 
1849
            else
 
1850
            {
 
1851
              WriteCell(h,s.SubString(j,sep-1), wxPDF_BORDER_NONE, context.GetFillStyle(), link);
 
1852
              i = sep + 1;
 
1853
            }
 
1854
            sep = -1;
 
1855
            j = i;
 
1856
            len = 0;
 
1857
            ns = 0;
 
1858
            nl++;
 
1859
            context.IncrementCurrentLine();
 
1860
            Ln();
 
1861
            DoXmlAlign(context);
 
1862
            wmax = context.GetCurrentLineWidth();
 
1863
          }
 
1864
          else
 
1865
          {
 
1866
            i++;
 
1867
          }
 
1868
        }
 
1869
        // Last chunk
 
1870
        WriteCell(h,s.SubString(j,i-1), wxPDF_BORDER_NONE, context.GetFillStyle(), link);
 
1871
        context.AddCurrentLineWidth(-len);
 
1872
        if (context.GetHAlign() == wxPDF_ALIGN_JUSTIFY && m_ws > 0)
 
1873
        {
 
1874
          double delta = ns * m_ws;
 
1875
          SetXY(GetX()+delta, GetY());
 
1876
        }
 
1877
      }
 
1878
    }
 
1879
    child = child->GetNext();
 
1880
  }
 
1881
}
 
1882
 
 
1883
void
 
1884
wxPdfDocument::DoXmlAlign(wxPdfCellContext& context)
 
1885
{
 
1886
  if (!context.GetAligned())
 
1887
  {
 
1888
    if (m_ws > 0 && context.GetHAlign() != wxPDF_ALIGN_JUSTIFY)
 
1889
    {
 
1890
      m_ws = 0;
 
1891
      Out("0 Tw");
 
1892
    }
 
1893
    switch (context.GetHAlign())
 
1894
    {
 
1895
      case wxPDF_ALIGN_JUSTIFY:
 
1896
        {
 
1897
          m_ws = (!context.IsCurrentLineMarked() && context.GetCurrentLineSpaces() > 0) ? (context.GetMaxWidth() - context.GetCurrentLineWidth())/context.GetCurrentLineSpaces() : 0;
 
1898
          OutAscii(wxPdfUtility::Double2String(m_ws*m_k,3)+wxString(wxT(" Tw")));
 
1899
        }
 
1900
        break;
 
1901
      case wxPDF_ALIGN_CENTER:
 
1902
        {
 
1903
          double delta = 0.5 * (context.GetMaxWidth() - context.GetCurrentLineWidth());
 
1904
          SetXY(GetX()+delta,GetY());
 
1905
        }
 
1906
        break;
 
1907
      case wxPDF_ALIGN_RIGHT:
 
1908
        {
 
1909
          double delta = context.GetMaxWidth() - context.GetCurrentLineWidth();
 
1910
          SetXY(GetX()+delta,GetY());
 
1911
        }
 
1912
        break;
 
1913
      case wxPDF_ALIGN_LEFT:
 
1914
      default:
 
1915
        break;
 
1916
    }
 
1917
  }
 
1918
  context.SetAligned();
 
1919
}