FreeCAD

Форк
0
/
SoFCVectorizeSVGAction.cpp 
487 строк · 14.8 Кб
1
/***************************************************************************
2
 *   Copyright (c) 2008 Werner Mayer <wmayer[at]users.sourceforge.net>     *
3
 *                                                                         *
4
 *   This file is part of the FreeCAD CAx development system.              *
5
 *                                                                         *
6
 *   This library is free software; you can redistribute it and/or         *
7
 *   modify it under the terms of the GNU Library General Public           *
8
 *   License as published by the Free Software Foundation; either          *
9
 *   version 2 of the License, or (at your option) any later version.      *
10
 *                                                                         *
11
 *   This library  is distributed in the hope that it will be useful,      *
12
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
13
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
14
 *   GNU Library General Public License for more details.                  *
15
 *                                                                         *
16
 *   You should have received a copy of the GNU Library General Public     *
17
 *   License along with this library; see the file COPYING.LIB. If not,    *
18
 *   write to the Free Software Foundation, Inc., 59 Temple Place,         *
19
 *   Suite 330, Boston, MA  02111-1307, USA                                *
20
 *                                                                         *
21
 ***************************************************************************/
22

23
#include "PreCompiled.h"
24

25
#ifndef _PreComp_
26
# include <qglobal.h>
27
# include <iomanip>
28
# include <ios>
29
# include <Inventor/SbBSPTree.h>
30
#endif
31

32
#include <Base/FileInfo.h>
33

34
#include "SoFCVectorizeSVGAction.h"
35

36

37
using namespace Gui;
38

39
class SoVectorizeItem {
40
public:
41
    SoVectorizeItem() {
42
        this->type = UNDEFINED;
43
        this->depth = 0.0f;
44
    }
45
    // quick and easy type system
46
    enum Type {
47
        UNDEFINED,
48
        LINE,
49
        TRIANGLE,
50
        TEXT,
51
        POINT,
52
        IMAGE
53
    };
54
    int type;
55
    float depth; // for depth sorting
56
};
57

58
class SoVectorizePoint : public SoVectorizeItem {
59
public:
60
    SoVectorizePoint() {
61
        this->type = POINT;
62
        this->vidx = 0;
63
        this->size = 1.0f;
64
        this->col = 0;
65
    }
66
    int vidx;       // index to BSPtree coordinate
67
    float size;     // Coin size (pixels)
68
    uint32_t col;
69
};
70

71
class SoVectorizeTriangle : public SoVectorizeItem {
72
public:
73
    SoVectorizeTriangle() {
74
        this->type = TRIANGLE;
75
    }
76
    int vidx[3];      // indices to BSPtree coordinates
77
    uint32_t col[3];
78
};
79

80
class SoVectorizeLine : public SoVectorizeItem {
81
public:
82
    SoVectorizeLine() {
83
        this->type = LINE;
84
        vidx[0] = 0;
85
        vidx[1] = 0;
86
        col[0] = 0;
87
        col[1] = 0;
88
        this->pattern = 0xffff;
89
        this->width = 1.0f;
90
    }
91
    int vidx[2];       // indices to BSPtree coordinates
92
    uint32_t col[2];
93
    uint16_t pattern;  // Coin line pattern
94
    float width;       // Coin line width (pixels)
95
};
96

97
class SoVectorizeText : public SoVectorizeItem {
98
public:
99
    SoVectorizeText() {
100
        this->type = TEXT;
101
        this->fontsize = 10;
102
        this->col = 0;
103
        this->justification = LEFT;
104
    }
105

106
    enum Justification {
107
        LEFT,
108
        RIGHT,
109
        CENTER
110
    };
111

112
    SbName fontname;
113
    float fontsize;    // size in normalized coordinates
114
    SbString string;
115
    SbVec2f pos;       // pos in normalized coordinates
116
    uint32_t col;
117
    Justification justification;
118
};
119

120
class SoVectorizeImage : public SoVectorizeItem {
121
public:
122
    SoVectorizeImage() {
123
        this->type = IMAGE;
124
        this->image.data = nullptr;
125
        this->image.nc = 0;
126
    }
127

128
    SbVec2f pos;        // pos in normalized coordinates
129
    SbVec2f size;       // size in normalized coordinates
130

131
    struct Image {
132
        const unsigned char * data;
133
        SbVec2s size;
134
        int nc;
135
    } image;
136
};
137

138
// ----------------------------------------------------------------
139

140
SoSVGVectorOutput::SoSVGVectorOutput() = default;
141

142
SoSVGVectorOutput::~SoSVGVectorOutput()
143
{
144
    closeFile();
145
}
146

147
SbBool SoSVGVectorOutput::openFile (const char *filename)
148
{
149
    Base::FileInfo fi(filename);
150
#ifdef _MSC_VER
151
    this->file.open(fi.toStdWString().c_str(), std::ios::out | std::ios::binary);
152
#else
153
    this->file.open(fi.filePath().c_str(), std::ios::out | std::ios::binary);
154
#endif
155

156
    return this->file.is_open();
157
}
158

159
void SoSVGVectorOutput::closeFile ()
160
{
161
    if (this->file.is_open())
162
        this->file.close();
163
}
164

165
std::fstream& SoSVGVectorOutput::getFileStream()
166
{
167
    return this->file;
168
}
169

170
// ----------------------------------------------------------------
171

172
namespace Gui {
173
class SoFCVectorizeSVGActionP
174
{
175
public:
176
    SoFCVectorizeSVGActionP(SoFCVectorizeSVGAction * p) {
177
        this->publ = p;
178
    }
179

180
    void printCircle(const SbVec3f & v, const SbColor & c, const float radius) const;
181
    void printSquare(const SbVec3f & v, const SbColor & c, const float size) const;
182
    void printTriangle(const SbVec3f * v, const SbColor * c) const;
183
    void printTriangle(const SoVectorizeTriangle * item) const;
184
    void printLine(const SoVectorizeLine * item) const;
185
    void printPoint(const SoVectorizePoint * item) const;
186
    void printText(const SoVectorizeText * item) const;
187
    void printImage(const SoVectorizeImage * item) const;
188

189
private:
190
    SoFCVectorizeSVGAction * publ;
191
};
192
}
193

194
void SoFCVectorizeSVGActionP::printText(const SoVectorizeText * item) const
195
{
196
    SbVec2f mul = publ->getRotatedViewportSize();
197
    SbVec2f add = publ->getRotatedViewportStartpos();
198
    float posx = item->pos[0]*mul[0]+add[0];
199
    float posy = item->pos[1]*mul[1]+add[1];
200

201
    std::ostream& str = publ->getSVGOutput()->getFileStream();
202
    str << "<text x=\"" << posx << "\" y=\"" << posy << "\" "
203
           "font-size=\"" << item->fontsize * mul[1] << "px\">"
204
        << item->string.getString() << "</text>" << std::endl;
205
}
206

207
void SoFCVectorizeSVGActionP::printTriangle(const SoVectorizeTriangle * item) const
208
{
209
    SbVec2f mul = publ->getRotatedViewportSize();
210
    SbVec2f add = publ->getRotatedViewportStartpos();
211

212
    const SbBSPTree & bsp = publ->getBSPTree();
213

214
    SbVec3f v[3];
215
    SbColor c[3];
216
    float t[3];
217

218
    for (int i = 0; i < 3; i++) {
219
        v[i] = bsp.getPoint(item->vidx[i]);
220
        v[i][0] = (v[i][0] * mul[0]) + add[0];
221
        v[i][1] = ((1.0f-v[i][1]) * mul[1]) + add[1];
222
        c[i].setPackedValue(item->col[i], t[i]);
223
    }
224
    this->printTriangle((SbVec3f*)v, (SbColor*)c);
225
}
226
/* TODO: Support gradients, e.g.
227
  <defs>
228
    <linearGradient id="verlauf" x1="0%" y1="100%" x2="100%" y2="100%">
229
      <stop offset="0%" stop-color="black" stop-opacity="100%" />
230
      <stop offset="100%" stop-color="white" stop-opacity="50%" />
231
    </linearGradient>
232
  </defs>
233
*/
234
/* Example: color per vertex
235
#Inventor V2.1 ascii
236
Separator {
237

238
  Coordinate3 {
239
    point [ 0.000000  0.000000  0.000000,
240
        100.000000  50.000000  0.000000,
241
        0.000000  100.000000  0.000000 ]
242

243
  }
244
  Material {
245
    diffuseColor [ 1 1 0, 0 0 1, 1 0 0 ]
246
  }
247

248
  MaterialBinding {
249
    value PER_VERTEX
250
  }
251
  IndexedFaceSet {
252
    coordIndex [ 0, 1, 2, -1 ]
253
  }
254
}
255

256
<?xml version="1.0"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
257
    "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
258
<svg width="100" height="100" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
259
    <defs>
260
        <linearGradient id="red" gradientUnits="userSpaceOnUse" x1="0" y1="0" x2="35" y2="80">
261
            <stop offset="0" stop-color="rgb(255,0,0)" stop-opacity="1"/>
262
            <stop offset="1" stop-color="rgb(255,0,0)" stop-opacity="0"/>
263
        </linearGradient>
264
        <linearGradient id="blue" gradientUnits="userSpaceOnUse" x1="100" y1="50" x2="0" y2="50">
265
            <stop offset="0" stop-color="rgb(0,0,255)" stop-opacity="1"/>
266
            <stop offset="1" stop-color="rgb(0,0,255)" stop-opacity="0"/>
267
        </linearGradient>
268
        <linearGradient id="yellow" gradientUnits="userSpaceOnUse" x1="0" y1="100" x2="40" y2="20">
269
            <stop offset="0" stop-color="rgb(255,255,0)" stop-opacity="1"/>
270
            <stop offset="1" stop-color="rgb(255,255,0)" stop-opacity="0"/>
271
        </linearGradient>
272
        <path id="triangle1" d="M0 0 L100 50 L0 100 z"/>
273
<filter id="colorAdd">
274
    <feComposite in="SourceGraphic" in2="BackgroundImage" operator="arithmetic" k2="1" k3="1"/>
275
</filter>
276
<filter id="Matrix1">
277
    <feColorMatrix type="matrix" values="
278
    1 0 0 0 0
279
    0 1 0 0 0
280
    0 0 1 0 0
281
    1 1 1 1 0
282
    0 0 0 0 1
283
    "/>
284
</filter>
285
</defs>
286
<g filter="url(#Matrix1)">
287
    <use xlink:href="#triangle1" fill="url(#blue)"/>
288
    <use xlink:href="#triangle1" fill="url(#yellow)" filter="url(#colorAdd)"/>
289
    <use xlink:href="#triangle1" fill="url(#red)" filter="url(#colorAdd)"/>
290
</g>
291
</svg>
292
*/
293
void SoFCVectorizeSVGActionP::printTriangle(const SbVec3f * v, const SbColor * c) const
294
{
295
    if (v[0] == v[1] || v[1] == v[2] || v[0] == v[2])
296
        return;
297
    uint32_t cc = c->getPackedValue();
298

299
    std::ostream& str = publ->getSVGOutput()->getFileStream();
300
    str << "<path d=\"M "
301
        << v[2][0] << "," << v[2][1] << " L "
302
        << v[1][0] << "," << v[1][1] << " "
303
        << v[0][0] << "," << v[0][1] << " z\"" << std::endl
304
        << "    style=\"fill:#"
305
        << std::hex << std::setw(6) << std::setfill('0') << (cc >> 8)
306
        << "; stroke:#"
307
        << std::hex << std::setw(6) << std::setfill('0') << (cc >> 8)
308
        << ";" << std::endl
309
        << "    stroke-width:" << publ->getLineWidth() << ";" << std::endl
310
        << "    stroke-linecap:round;stroke-linejoin:round\"/>" << std::endl;
311
}
312

313
void SoFCVectorizeSVGActionP::printCircle(const SbVec3f & v, const SbColor & c, const float radius) const
314
{
315
    // todo
316
    Q_UNUSED(v);
317
    Q_UNUSED(c);
318
    Q_UNUSED(radius);
319
}
320

321
void SoFCVectorizeSVGActionP::printSquare(const SbVec3f & v, const SbColor & c, const float size) const
322
{
323
    // todo
324
    Q_UNUSED(v);
325
    Q_UNUSED(c);
326
    Q_UNUSED(size);
327
}
328

329
void SoFCVectorizeSVGActionP::printLine(const SoVectorizeLine * item) const
330
{
331
    SbVec2f mul = publ->getRotatedViewportSize();
332
    SbVec2f add = publ->getRotatedViewportStartpos();
333

334
    const SbBSPTree & bsp = publ->getBSPTree();
335

336
    SbVec3f v[2];
337
    SbColor c[2];
338
    float t[2];
339

340
    for (int i = 0; i < 2; i++) {
341
        v[i] = bsp.getPoint(item->vidx[i]);
342
        v[i][0] = (v[i][0] * mul[0]) + add[0];
343
        v[i][1] = ((1.0f-v[i][1]) * mul[1]) + add[1];
344
        c[i].setPackedValue(item->col[i], t[i]);
345
    }
346
    uint32_t cc = c[0].getPackedValue();
347

348
    std::ostream& str = publ->getSVGOutput()->getFileStream();
349
    str << "<line "
350
        << "x1=\"" << v[0][0] << "\" y1=\"" << v[0][1] << "\" "
351
        << "x2=\"" << v[1][0] << "\" y2=\"" << v[1][1] << "\" "
352
        << "stroke=\"#"
353
        << std::hex << std::setw(6) << std::setfill('0') << (cc >> 8) << "\""
354
        << " stroke-linecap=\"square\" "
355
        << " stroke-width=\"" << publ->getLineWidth() << "\" />\n";
356
}
357

358
void SoFCVectorizeSVGActionP::printPoint(const SoVectorizePoint * item) const
359
{
360
    // todo
361
    Q_UNUSED(item);
362
}
363

364
void SoFCVectorizeSVGActionP::printImage(const SoVectorizeImage * item) const
365
{
366
    // todo
367
    Q_UNUSED(item);
368
}
369

370
// -------------------------------------------------------
371

372
SO_ACTION_SOURCE(SoFCVectorizeSVGAction)
373

374
void SoFCVectorizeSVGAction::initClass()
375
{
376
    SO_ACTION_INIT_CLASS(SoFCVectorizeSVGAction, SoVectorizeAction);
377
}
378

379
SoFCVectorizeSVGAction::SoFCVectorizeSVGAction()
380
{
381
    SO_ACTION_CONSTRUCTOR(SoFCVectorizeSVGAction);
382
    this->setOutput(new SoSVGVectorOutput);
383
    this->p = new SoFCVectorizeSVGActionP(this);
384
}
385

386
SoFCVectorizeSVGAction::~SoFCVectorizeSVGAction()
387
{
388
    delete this->p;
389
}
390

391
SoSVGVectorOutput *
392
SoFCVectorizeSVGAction::getSVGOutput() const
393
{
394
    return static_cast<SoSVGVectorOutput*>(SoVectorizeAction::getOutput());
395
}
396

397
void SoFCVectorizeSVGAction::printHeader() const
398
{
399
    std::ostream& str = this->getSVGOutput()->getFileStream();
400
    str << R"(<?xml version="1.0" encoding="UTF-8" standalone="no"?>)" << std::endl;
401
    str << "<!-- Created with FreeCAD (https://www.freecad.org) -->" << std::endl;
402
    str << "<svg xmlns=\"http://www.w3.org/2000/svg\"" << std::endl;
403
    str << R"(     xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:ev="http://www.w3.org/2001/xml-events")" << std::endl;
404
    str << R"(     version="1.1" baseProfile="full")"  << std::endl;
405

406
    SbVec2f size = getPageSize();
407
    if (this->getOrientation() == LANDSCAPE) {
408
        SbSwap<float>(size[0], size[1]);
409
    }
410
    if (getUseMM()) {
411
        str << "     width=\"" << size[0] << "mm\" height=\"" << size[1] << "mm\""<< std::endl;
412
        str << "     viewBox=\"0 0 " << size[0] << " " << size[1] << "\">" << std::endl;
413
    } else {            //original code used px
414
        str << "     width=\"" << size[0] << "\" height=\"" << size[1] << "\">" << std::endl;
415
    }
416
    str << "<g>" << std::endl;
417
}
418

419
void SoFCVectorizeSVGAction::printFooter() const
420
{
421
    std::ostream& str = this->getSVGOutput()->getFileStream();
422
    str << "</g>" << std::endl;
423
    str << "</svg>";
424
}
425

426
void SoFCVectorizeSVGAction::printViewport() const
427
{
428
}
429

430
void SoFCVectorizeSVGAction::printBackground() const
431
{
432
    if (!getBackgroundState()) {
433
        return;
434
    }
435
    SbVec2f mul = getRotatedViewportSize();
436
    SbVec2f add = getRotatedViewportStartpos();
437

438
    float x[2],y[2];
439
    x[0] = add[0];
440
    x[1] = mul[0] - add[0];
441
    y[0] = add[1];
442
    y[1] = mul[1] - add[1];
443

444
    SbColor bg;
445
    (void)this->getBackgroundColor(bg);
446
    uint32_t cc = bg.getPackedValue();
447

448
    std::ostream& str = this->getSVGOutput()->getFileStream();
449
    str << "</g>" << std::endl;
450
    str << "<path" << std::endl;
451
    str << "   d=\"M "
452
        << x[0] << "," << y[0] << " L "
453
        << x[1] << "," << y[0] << " L "
454
        << x[1] << "," << y[1] << " L "
455
        << x[0] << "," << y[1] << " L "
456
        << x[0] << "," << y[0] << " z \"" << std::endl;
457
    str << "   style=\"fill:#"
458
        << std::hex << std::setw(6) << std::setfill('0') << (cc >> 8)
459
        << ";fill-opacity:1;fill-rule:evenodd;stroke:none;"
460
           "stroke-width:" << getLineWidth() << ";stroke-linecap:butt;stroke-linejoin:"
461
           "miter;stroke-opacity:1\" />\n";
462
    str << "<g>" << std::endl;
463
}
464

465
void SoFCVectorizeSVGAction::printItem(const SoVectorizeItem * item) const
466
{
467
    switch (item->type) {
468
    case SoVectorizeItem::TRIANGLE:
469
        this->p->printTriangle(static_cast<const SoVectorizeTriangle*>(item));
470
        break;
471
    case SoVectorizeItem::LINE:
472
        this->p->printLine(static_cast<const SoVectorizeLine*>(item));
473
        break;
474
    case SoVectorizeItem::POINT:
475
        this->p->printPoint(static_cast<const SoVectorizePoint*>(item));
476
        break;
477
    case SoVectorizeItem::TEXT:
478
        this->p->printText(static_cast<const SoVectorizeText*>(item));
479
        break;
480
    case SoVectorizeItem::IMAGE:
481
        this->p->printImage(static_cast<const SoVectorizeImage*>(item));
482
        break;
483
    default:
484
        assert(0 && "unsupported item");
485
        break;
486
    }
487
}
488

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.