/*
6 * Ulf Erikson <ulferikson@users.sf.net>
7 * Jon A. Cruz <jon@joncruz.org>
11 * Copyright (C) 2006-2009 Authors
13 * Released under GNU GPL v2+, read the file
'COPYING' for more information.
16 * - How to Create & Play Enhanced Metafiles in Win32
18 * - INFO: Windows Metafile Functions & Aldus Placeable Metafiles
20 * - Metafile Functions
22 * - Metafile Structures
29#include <glibmm/miscutils.h>
74#define PXPERMETER 2835
87 const char *cptr = &
string[strlen(
string) + 1];
91 sscanf(cptr,
"%7d", ndx);
96 ladx = (uint32_t *) malloc(*ndx *
sizeof(uint32_t));
98 g_message(
"Out of memory");
101 for (i = 0; i < *ndx; i++, cptr += 7, ladx++) {
102 sscanf(cptr,
"%7f", &fdx);
103 *ladx = (uint32_t) round(fdx *
scale);
106 sscanf(cptr,
"%7f", &fdx);
109 sscanf(cptr,
"%07d", rtl);
129 gchar
const *utf8_fn = mod->get_param_string(
"destination");
140 (void) emf_start(utf8_fn, 1000000, 250000, &
et);
141 (void) htable_create(128, 128, &
eht);
143 char *ansi_uri = (
char *) utf8_fn;
155 const char *p1 = nv->
attribute(
"pagecolor");
157 uint32_t lc = strtoul(&p1[1], &p2, 16);
162 gv.
rgb[0] = (float) U_RGBAGetR(
gv.
bgc) / 255.0;
163 gv.
rgb[1] = (float) U_RGBAGetG(
gv.
bgc) / 255.0;
164 gv.
rgb[2] = (float) U_RGBAGetB(
gv.
bgc) / 255.0;
167 bool pageBoundingBox;
168 pageBoundingBox = mod->get_param_bool(
"pageBoundingBox");
171 if (pageBoundingBox) {
183 float dwInchesX = d.
width();
184 float dwInchesY = d.
height();
187 (void) drawing_size((
int) ceil(dwInchesX * 25.4), (int) ceil(dwInchesY * 25.4),1200.0/25.4, &rclBounds, &rclFrame);
192 (void) device_size(MMX, MMY, 1200.0 / 25.4, &szlDev, &szlMm);
193 int PixelsX = szlDev.
cx;
194 int PixelsY = szlDev.
cy;
198 memset(buff, 0,
sizeof(buff));
199 char *p1 = strrchr(ansi_uri,
'\\');
200 char *p2 = strrchr(ansi_uri,
'/');
201 char *p =
MAX(p1, p2);
213 rec = U_EMRHEADER_set(rclBounds, rclFrame,
nullptr, cbDesc, Description, szlDev, szlMm, 0);
216 g_error(
"Fatal programming error in PrintEmf::begin at EMRHEADER");
221 rec = U_EMRSETMAPMODE_set(U_MM_TEXT);
223 g_error(
"Fatal programming error in PrintEmf::begin at EMRSETMAPMODE");
233 worldTransform.
eM11 = 1.0;
234 worldTransform.
eM12 = 0.0;
235 worldTransform.
eM21 = 0.0;
236 worldTransform.
eM22 = 1.0;
237 worldTransform.
eDx = 0;
238 worldTransform.
eDy = 0;
240 rec = U_EMRMODIFYWORLDTRANSFORM_set(worldTransform, U_MWT_LEFTMULTIPLY);
242 g_error(
"Fatal programming error in PrintEmf::begin at EMRMODIFYWORLDTRANSFORM");
247 snprintf(buff,
sizeof(buff) - 1,
"Screen=%dx%dpx, %dx%dmm", PixelsX, PixelsY, MMX, MMY);
248 rec = textcomment_set(buff);
250 g_error(
"Fatal programming error in PrintEmf::begin at textcomment_set 1");
253 snprintf(buff,
sizeof(buff) - 1,
"Drawing=%.1fx%.1fpx, %.1fx%.1fmm", doc->
preferredBounds()->width(),
256 rec = textcomment_set(buff);
258 g_error(
"Fatal programming error in PrintEmf::begin at textcomment_set 1");
264 rec = U_EMRSETBKMODE_set(U_TRANSPARENT);
266 g_error(
"Fatal programming error in PrintEmf::begin at U_EMRSETBKMODE_set");
270 rec = U_EMRSETPOLYFILLMODE_set(U_WINDING);
272 g_error(
"Fatal programming error in PrintEmf::begin at U_EMRSETPOLYFILLMODE_set");
280 rec = U_EMRSETTEXTALIGN_set(U_TA_BASELINE | U_TA_LEFT);
282 g_error(
"Fatal programming error in PrintEmf::begin at U_EMRSETTEXTALIGN_set");
286 rec = U_EMRSETTEXTCOLOR_set(U_RGB(0, 0, 0));
288 g_error(
"Fatal programming error in PrintEmf::begin at U_EMRSETTEXTCOLOR_set");
291 rec = U_EMRSETROP2_set(U_R2_COPYPEN);
293 g_error(
"Fatal programming error in PrintEmf::begin at U_EMRSETROP2_set");
313 rec = U_EMREOF_set(0,
nullptr,
et);
315 g_error(
"Fatal programming error in PrintEmf::finish");
317 (void) emf_finish(
et,
eht);
329 uint32_t brush, fmode;
346 brushStyle = U_BS_SOLID;
347 hatchType = U_HS_SOLIDCLR;
348 bkColor = U_RGB(0, 0, 0);
350 hatchColor = *fcolor;
352 hatchColor = U_RGB(0, 0, 0);
355 if (!fcolor && style) {
356 if (style->
fill.isColor()) {
360 float opacity = SP_SCALE24_TO_FLOAT(style->
fill_opacity.value);
361 if (opacity <= 0.0) {
365 auto rgb = *style->
fill.getColor().converted(Space::Type::RGB);
366 hatchColor = U_RGB(255 *
rgb[0], 255 *
rgb[1], 255 *
rgb[2]);
368 fmode = style->
fill_rule.computed == 0 ? U_WINDING : (style->
fill_rule.computed == 2 ? U_ALTERNATE : U_ALTERNATE);
369 }
else if (is<SPPattern>(SP_STYLE_FILL_SERVER(style))) {
371 auto pat = cast<SPPattern>(paintserver);
372 double dwidth = pat->width();
373 double dheight = pat->height();
376 brush_classify(pat, 0, &pixbuf, &hatchType, &hatchColor, &bkColor);
381 if (hatchType == -1) {
382 hatchType = U_HS_CROSS;
383 hatchColor = U_RGB(0xFF, 0xC3, 0xC3);
387 if (hatchType == -1) {
389 hatchType = U_HS_DIAGCROSS;
390 hatchColor = U_RGB(0xFF, 0xC3, 0xC3);
393 brushStyle = U_BS_HATCHED;
394 }
else if (is<SPGradient>(SP_STYLE_FILL_SERVER(style))) {
400 if (is<SPLinearGradient>(paintserver)) {
401 lg = cast<SPLinearGradient>(paintserver);
404 }
else if (is<SPRadialGradient>(paintserver)) {
405 rg = cast<SPRadialGradient>(paintserver);
430 lb = logbrush_set(brushStyle, hatchColor, hatchType);
439 rec = U_EMRSETBKCOLOR_set(bkColor);
441 g_error(
"Fatal programming error in PrintEmf::create_brush at U_EMRSETBKCOLOR_set");
443 rec = U_EMRSETBKMODE_set(U_OPAQUE);
445 g_error(
"Fatal programming error in PrintEmf::create_brush at U_EMRSETBKMODE_set");
448 rec = createbrushindirect_set(&brush,
eht, lb);
450 g_error(
"Fatal programming error in PrintEmf::create_brush at createbrushindirect_set");
462 rgba_px = (
char const*) pixbuf->
pixels();
463 colortype = U_BCBM_COLOR32;
464 (void) RGBA_to_DIB(&px, &cbPx, &ct, &numCt, rgba_px,
width,
height,
width * 4, colortype, 0, 1);
467 Bmih = bitmapinfoheader_set(
width,
height, 1, colortype, U_BI_RGB, 0, PXPERMETER, PXPERMETER, numCt, 0);
468 Bmi = bitmapinfo_set(Bmih, ct);
469 rec = createdibpatternbrushpt_set(&brush,
eht, U_DIB_RGB_COLORS, Bmi, cbPx, px);
471 g_error(
"Fatal programming error in PrintEmf::create_brush at createdibpatternbrushpt_set");
479 rec = selectobject_set(brush,
eht);
481 g_error(
"Fatal programming error in PrintEmf::create_brush at selectobject_set");
486 rec = U_EMRSETPOLYFILLMODE_set(fmode);
488 g_error(
"Fatal programming error in PrintEmf::create_brush at U_EMRSETPOLYdrawmode_set");
502 rec = selectobject_set(U_NULL_BRUSH,
eht);
504 g_error(
"Fatal programming error in PrintEmf::destroy_brush at selectobject_set");
509 g_error(
"Fatal programming error in PrintEmf::destroy_brush");
522 int linestyle = U_PS_SOLID;
546 brushStyle = U_BS_SOLID;
547 hatchColor = U_RGB(0, 0, 0);
548 hatchType = U_HS_HORIZONTAL;
549 bkColor = U_RGB(0, 0, 0);
552 if (is<SPPattern>(SP_STYLE_STROKE_SERVER(style))) {
554 auto pat = cast<SPPattern>(paintserver);
555 double dwidth = pat->width();
556 double dheight = pat->height();
559 brush_classify(pat, 0, &pixbuf, &hatchType, &hatchColor, &bkColor);
561 brushStyle = U_BS_DIBPATTERN;
562 rgba_px = (
char *) pixbuf->
pixels();
563 colortype = U_BCBM_COLOR32;
564 (void) RGBA_to_DIB(&px, &cbPx, &ct, &numCt, rgba_px,
width,
height,
width * 4, colortype, 0, 1);
567 Bmih = bitmapinfoheader_set(
width,
height, 1, colortype, U_BI_RGB, 0, PXPERMETER, PXPERMETER, numCt, 0);
568 Bmi = bitmapinfo_set(Bmih, ct);
570 brushStyle = U_BS_HATCHED;
572 rec = U_EMRSETBKCOLOR_set(bkColor);
574 g_error(
"Fatal programming error in PrintEmf::create_pen at U_EMRSETBKCOLOR_set");
576 rec = U_EMRSETBKMODE_set(U_OPAQUE);
578 g_error(
"Fatal programming error in PrintEmf::create_pen at U_EMRSETBKMODE_set");
581 if (hatchType == -1) {
582 hatchType = U_HS_CROSS;
583 hatchColor = U_RGB(0xFF, 0xC3, 0xC3);
587 if (hatchType == -1) {
588 brushStyle = U_BS_HATCHED;
589 hatchType = U_HS_DIAGCROSS;
590 hatchColor = U_RGB(0xFF, 0xC3, 0xC3);
593 }
else if (is<SPGradient>(SP_STYLE_STROKE_SERVER(style))) {
597 if (is<SPLinearGradient>(paintserver)) {
598 auto lg = cast<SPLinearGradient>(paintserver);
605 if (lg->gradientTransform_set) {
606 p1 = p1 * lg->gradientTransform;
607 p2 = p2 * lg->gradientTransform;
610 }
else if (is<SPRadialGradient>(paintserver)) {
611 auto rg = cast<SPRadialGradient>(paintserver);
614 double r = rg->r.computed;
621 if (rg->gradientTransform_set) {
622 c =
c * rg->gradientTransform;
623 yhandle_point = yhandle_point * rg->gradientTransform;
624 xhandle_point = xhandle_point * rg->gradientTransform;
630 }
else if (style->
stroke.isColor()) {
631 auto rgb = *style->
stroke.getColor().converted(Space::Type::RGB);
632 brushStyle = U_BS_SOLID;
633 hatchColor = U_RGB(255 *
rgb[0], 255 *
rgb[1], 255 *
rgb[2]);
634 hatchType = U_HS_SOLIDCLR;
650 double scale = sqrt((p[X] * p[X]) + (p[Y] * p[Y])) / sqrt(2);
658 linecap = U_PS_ENDCAP_FLAT;
660 linecap = U_PS_ENDCAP_ROUND;
662 linecap = U_PS_ENDCAP_SQUARE;
666 linejoin = U_PS_JOIN_MITER;
668 linejoin = U_PS_JOIN_ROUND;
670 linejoin = U_PS_JOIN_BEVEL;
675 brushStyle = U_BS_SOLID;
676 hatchType = U_HS_HORIZONTAL;
679 while ((linestyle != U_PS_USERSTYLE) && (i < style->stroke_dasharray.values.size())) {
681 linestyle = U_PS_USERSTYLE;
686 if (linestyle == U_PS_USERSTYLE) {
688 dash =
new uint32_t[n_dash];
689 for (i = 0; i < n_dash; i++) {
697 U_PS_GEOMETRIC | linestyle | linecap | linejoin,
717 rec = extcreatepen_set(&pen,
eht, Bmi, cbPx, px, elp);
719 g_error(
"Fatal programming error in PrintEmf::create_pen at extcreatepen_set");
729 rec = selectobject_set(pen,
eht);
731 g_error(
"Fatal programming error in PrintEmf::create_pen at selectobject_set");
735 if (linejoin == U_PS_JOIN_MITER) {
738 if (miterlimit < 1) {
742 rec = U_EMRSETMITERLIMIT_set((uint32_t) miterlimit);
744 g_error(
"Fatal programming error in PrintEmf::create_pen at U_EMRSETMITERLIMIT_set");
761 rec = selectobject_set(U_NULL_PEN,
eht);
763 g_error(
"Fatal programming error in PrintEmf::destroy_pen at selectobject_set");
766 rec = deleteobject_set(&
hpen,
eht);
768 g_error(
"Fatal programming error in PrintEmf::destroy_pen");
793 if(pit->end_closed() != pit->end_default())
return(bad);
794 if(pit2 != pv.
end())
return(bad);
795 P1_trail = pit->finalPoint();
797 P1 = cit->initialPoint();
798 for(;cit != pit->end_closed();++cit) {
803 P1_lead = cit->finalPoint();
805 v1 = unit_vector(P1 - P1_trail);
806 v2 = unit_vector(P1_lead - P1 );
814 output.
close( pit->closed() );
851 P1_trail = cit->initialPoint();
852 P1 = cit->finalPoint();
853 v1 = unit_vector(P1 - P1_trail);
856 if(fabs(
ang) < fabs(*angle))*angle = -
ang;
862 double convert = 36000.0/ (2.0 * M_PI);
863 *angle = round(*angle * convert)/convert;
868 P1_trail = cit->initialPoint();
869 P1 = cit->finalPoint();
870 v1 = unit_vector(P1 - P1_trail);
876 if(vertex_count == 4){
915 center += cit->initialPoint()/4.0;
916 if(cit == pathRect.
end_open())
break;
944 P1 = cit->initialPoint();
946 if ( ( LR == (
dot(P1 - center,v1) > 0 ? 0 : 1) )
947 && ( UL == (
dot(P1 - center,v2) > 0 ? 1 : 0) ) )
break;
948 if(cit == pathRect.
end_open())
break;
957 tv.
x = (int32_t) round(Pt[X]);
958 tv.
y = (int32_t) round(Pt[Y]);
975 rec = U_EMRRESTOREDC_set(-1);
977 g_error(
"Fatal programming error in PrintEmf::fill at U_EMRRESTOREDC_set");
999 if(scp != scpActive){
1001 rec = U_EMRRESTOREDC_set(-1);
1003 g_error(
"Fatal programming error in PrintEmf::fill at U_EMRRESTOREDC_set");
1005 scpActive =
nullptr;
1015 scan_item = cast<SPItem>(scan_item->
parent);
1016 if(!scan_item)
break;
1029 if (is<SPGroup>(
item)) {
1032 }
else if (is<SPShape>(
item)) {
1038 if (!combined_pathvector.
empty()) {
1041 rec = U_EMRSAVEDC_set();
1043 g_error(
"Fatal programming error in PrintEmf::image at U_EMRSAVEDC_set");
1046 rec = U_EMRSELECTCLIPPATH_set(U_RGN_COPY);
1048 g_error(
"Fatal programming error in PrintEmf::do_clip_if_present at U_EMRSELECTCLIPPATH_set");
1052 scpActive =
nullptr;
1062 auto group = cast<SPGroup>(
item);
1068 for (
auto&
child: group->children) {
1073 if (is<SPGroup>(
item)) {
1075 }
else if (is<SPShape>(
item)) {
1080 return new_combined_pathvector;
1086 auto shape = cast<SPShape>(
item);
1090 return new_combined_pathvector;
1093 if (shape->curve()) {
1095 if(combined_pathvector.
empty()){
1096 new_combined_pathvector = new_vect * tfc;
1102 return new_combined_pathvector;
1125 bool is_Rect =
false;
1137 if(!rectDir)is_Rect =
false;
1155 double doff, doff_base, doff_range;
1156 double divisions = 128.0;
1173 double rx = hypot(xv[X], xv[Y]);
1174 double ry = hypot(yv[X], yv[Y]);
1175 double range = fmax(rx, ry);
1176 double step = range / divisions;
1177 double overlap = step / 4.0;
1193 for (
start = 0.0;
start < range;
start += step, doff += 1. / divisions) {
1194 stop =
start + step + overlap;
1198 wc =
weight_colors(c1, c2, (doff - doff_base) / (doff_range - doff_base));
1206 if (doff >= doff_range) {
1208 if (istop >= nstops) {
1212 doff_base = doff_range;
1227 double wRect, hRect;
1244 tmpTransform.
eM11 = tf2[0];
1245 tmpTransform.
eM12 = tf2[1];
1246 tmpTransform.
eM21 = tf2[2];
1247 tmpTransform.
eM22 = tf2[3];
1251 rec = U_EMRSAVEDC_set();
1253 g_error(
"Fatal programming error in PrintEmf::image at U_EMRSAVEDC_set");
1256 rec = U_EMRMODIFYWORLDTRANSFORM_set(tmpTransform, U_MWT_LEFTMULTIPLY);
1258 g_error(
"Fatal programming error in PrintEmf::image at EMRMODIFYWORLDTRANSFORM");
1261 for(;istop<nstops;istop++){
1263 if(rectDir == 1 || rectDir == 2){
1266 gMode = U_GRADIENT_FILL_RECT_H;
1271 gMode = U_GRADIENT_FILL_RECT_V;
1274 doff_base = doff_range;
1275 rcb.
left = round(outUL[X]);
1276 rcb.
top = round(outUL[Y]);
1277 rcb.
right = round(outLR[X]);
1278 rcb.
bottom = round(outLR[Y]);
1281 if(rectDir == 2 || rectDir == 4){
1292 rec = U_EMRGRADIENTFILL_set(rcb, 2, 1, gMode, ut, (uint32_t *) &ug4 );
1294 g_error(
"Fatal programming error in PrintEmf::fill at U_EMRGRADIENTFILL_set");
1298 rec = U_EMRRESTOREDC_set(-1);
1300 g_error(
"Fatal programming error in PrintEmf::fill at U_EMRRESTOREDC_set");
1307 double step = range / divisions;
1308 double overlap = step / 4.0;
1316 pathvc =
rect_cutter(
gv.
p1, uv * (overlap), uv * (-50000.0), puv * 50000.0);
1323 pathvc =
rect_cutter(
gv.
p2, uv * (-overlap), uv * (50000.0), puv * 50000.0);
1329 for (
start = 0.0;
start < range;
start += step, doff += 1. / divisions) {
1330 stop =
start + step + overlap;
1336 wc =
weight_colors(c1, c2, (doff - doff_base) / (doff_range - doff_base));
1341 if (doff >= doff_range) {
1343 if (istop >= nstops) {
1347 doff_base = doff_range;
1355 g_error(
"Fatal programming error in PrintEmf::fill, invalid gradient type detected");
1373 bool all_closed =
true;
1374 for (
const auto & pit : pathv) {
1376 if (pit.end_default() != pit.end_closed()) {
1401 char *rec =
nullptr;
1421 double slength = 0.0;
1423 for (
const auto & i : pathv) {
1424 tmp_pathpw.
concat(i.toPwSb());
1426 tlength = length(tmp_pathpw, 0.1);
1427 tmp_pathpw2 = arc_length_parametrization(tmp_pathpw);
1430 while (slength < tlength) {
1432 if (elength > tlength) {
1447 tmp_pathpw3.
concat(first_frag);
1459 rec = U_EMRSETBKMODE_set(U_TRANSPARENT);
1461 g_error(
"Fatal programming error in PrintEmf::stroke at U_EMRSETBKMODE_set");
1481 char *rec =
nullptr;
1483 for (
auto & pit : pv) {
1508 for (
auto & pit : pv) {
1517 int32_t
const x0 = (int32_t) round(p0[X]);
1518 int32_t
const y0 = (int32_t) round(p0[Y]);
1539 int32_t
const x1 = (int32_t) round(p1[X]);
1540 int32_t
const y1 = (int32_t) round(p1[Y]);
1546 std::vector<Geom::Point> points = cubic->controlPoints();
1563 int32_t
const x1 = (int32_t) round(p1[X]);
1564 int32_t
const y1 = (int32_t) round(p1[Y]);
1565 int32_t
const x2 = (int32_t) round(p2[X]);
1566 int32_t
const y2 = (int32_t) round(p2[Y]);
1567 int32_t
const x3 = (int32_t) round(p3[X]);
1568 int32_t
const y3 = (int32_t) round(p3[Y]);
1572 lpPoints[i + 1].
x = x2;
1573 lpPoints[i + 1].
y = y2;
1574 lpPoints[i + 2].
x = x3;
1575 lpPoints[i + 2].
y = y3;
1582 bool closed = (lpPoints[0].
x == lpPoints[i - 1].
x) && (lpPoints[0].y == lpPoints[i - 1].y);
1583 bool polygon =
false;
1584 bool rectangle =
false;
1585 bool ellipse =
false;
1587 if (moves == 1 && moves + lines == nodes && closed) {
1596 }
else if (moves == 1 && nodes == 5 && moves + curves == nodes && closed) {
1608 if (polygon || ellipse) {
1611 rec = selectobject_set(U_NULL_PEN,
eht);
1613 g_error(
"Fatal programming error in PrintEmf::print_simple_shape at selectobject_set pen");
1616 rec = selectobject_set(U_NULL_BRUSH,
eht);
1618 g_error(
"Fatal programming error in PrintEmf::print_simple_shape at selectobject_set brush");
1625 lpPoints[0].
x, lpPoints[0].
y
1627 lpPoints[2].
x, lpPoints[2].
y
1629 rec = U_EMRRECTANGLE_set(rcl);
1631 rec = U_EMRPOLYGON_set(U_RCL_DEF, nodes, lpPoints);
1633 }
else if (ellipse) {
1635 lpPoints[6].
x, lpPoints[3].
y
1637 lpPoints[0].
x, lpPoints[9].
y
1639 rec = U_EMRELLIPSE_set(rcl);
1642 g_error(
"Fatal programming error in PrintEmf::print_simple_shape at retangle/ellipse/polygon");
1649 rec = selectobject_set(
hpen,
eht);
1651 g_error(
"Fatal programming error in PrintEmf::print_simple_shape at selectobject_set pen");
1656 g_error(
"Fatal programming error in PrintEmf::print_simple_shape at selectobject_set brush");
1683 unsigned char *rgba_px,
1690 double x1, y1, dw, dh;
1691 char *rec =
nullptr;
1696 rec = U_EMRSETSTRETCHBLTMODE_set(U_COLORONCOLOR);
1698 g_error(
"Fatal programming error in PrintEmf::image at EMRHEADER");
1703 dw = ((double)
w) * tf_rect[0];
1704 dh = ((double) h) * tf_rect[3];
1715 colortype = U_BCBM_COLOR32;
1716 (void) RGBA_to_DIB(&px, &cbPx, &ct, &numCt, (
char *) rgba_px,
w, h,
w * 4, colortype, 0, 1);
1717 Bmih = bitmapinfoheader_set(
w, h, 1, colortype, U_BI_RGB, 0, PXPERMETER, PXPERMETER, numCt, 0);
1718 Bmi = bitmapinfo_set(Bmih, ct);
1729 tf[4] = tf[5] = 0.0;
1732 tmpTransform.
eM11 = tf[0];
1733 tmpTransform.
eM12 = tf[1];
1734 tmpTransform.
eM21 = tf[2];
1735 tmpTransform.
eM22 = tf[3];
1739 rec = U_EMRSAVEDC_set();
1741 g_error(
"Fatal programming error in PrintEmf::image at U_EMRSAVEDC_set");
1744 rec = U_EMRMODIFYWORLDTRANSFORM_set(tmpTransform, U_MWT_LEFTMULTIPLY);
1746 g_error(
"Fatal programming error in PrintEmf::image at EMRMODIFYWORLDTRANSFORM");
1749 rec = U_EMRSTRETCHDIBITS_set(
1762 g_error(
"Fatal programming error in PrintEmf::image at U_EMRSTRETCHDIBITS_set");
1771 rec = U_EMRRESTOREDC_set(-1);
1773 g_error(
"Fatal programming error in PrintEmf::image at U_EMRRESTOREDC_set");
1789 rec = U_EMRBEGINPATH_set();
1791 g_error(
"Fatal programming error in PrintEmf::print_pathv at U_EMRBEGINPATH_set");
1797 for (
const auto & pit : pv) {
1807 U_POINTL ptl = pointl_set((int32_t) round(p0[X]), (int32_t) round(p0[Y]));
1808 rec = U_EMRMOVETOEX_set(ptl);
1810 g_error(
"Fatal programming error in PrintEmf::print_pathv at U_EMRMOVETOEX_set");
1829 ptl = pointl_set((int32_t) round(p1[X]), (int32_t) round(p1[Y]));
1830 rec = U_EMRLINETO_set(ptl);
1832 g_error(
"Fatal programming error in PrintEmf::print_pathv at U_EMRLINETO_set");
1835 std::vector<Geom::Point> points = cubic->controlPoints();
1852 int32_t
const x1 = (int32_t) round(p1[X]);
1853 int32_t
const y1 = (int32_t) round(p1[Y]);
1854 int32_t
const x2 = (int32_t) round(p2[X]);
1855 int32_t
const y2 = (int32_t) round(p2[Y]);
1856 int32_t
const x3 = (int32_t) round(p3[X]);
1857 int32_t
const y3 = (int32_t) round(p3[Y]);
1867 rec = U_EMRPOLYBEZIERTO_set(U_RCL_DEF, 3, pt);
1869 g_error(
"Fatal programming error in PrintEmf::print_pathv at U_EMRPOLYBEZIERTO_set");
1872 g_warning(
"logical error, because pathv_to_linear_and_cubic_beziers was used");
1876 if (pit.end_default() == pit.end_closed()) {
1877 rec = U_EMRCLOSEFIGURE_set();
1879 g_error(
"Fatal programming error in PrintEmf::print_pathv at U_EMRCLOSEFIGURE_set");
1885 rec = U_EMRENDPATH_set();
1887 g_error(
"Fatal programming error in PrintEmf::print_pathv at U_EMRENDPATH_set");
1896 char *rec =
nullptr;
1913 rec = U_EMRFILLPATH_set(U_RCL_DEF);
1915 g_error(
"Fatal programming error in PrintEmf::fill at U_EMRFILLPATH_set");
1918 rec = U_EMRSTROKEANDFILLPATH_set(U_RCL_DEF);
1920 g_error(
"Fatal programming error in PrintEmf::stroke at U_EMRSTROKEANDFILLPATH_set");
1923 rec = U_EMRSTROKEPATH_set(U_RCL_DEF);
1925 g_error(
"Fatal programming error in PrintEmf::stroke at U_EMRSTROKEPATH_set");
1949 char *rec =
nullptr;
1950 int ccount, newfont;
1954 double rot = -1800.0 * std::atan2(tf[1], tf[0]) / M_PI;
1955 double rotb = -std::atan2(tf[1], tf[0]);
1964 uint32_t textalignment;
1966 textalignment = U_TA_BASELINE | U_TA_LEFT;
1968 textalignment = U_TA_BASELINE | U_TA_RIGHT | U_TA_RTLREADING;
1972 rec = U_EMRSETTEXTALIGN_set(textalignment);
1974 g_error(
"Fatal programming error in PrintEmf::text at U_EMRSETTEXTALIGN_set");
1978 char *text2 = strdup(
text);
2006 if (params.
f2 != 0 || params.
f3 != 0) {
2007 int irem = ((int) round(rot)) % 900 ;
2008 if (irem <= 9 && irem >= -9) {
2010 rot = (double)(((
int) round(rot)) - irem);
2011 rotb = rot * M_PI / 1800.0;
2012 if (std::abs(rot) == 900.0) {
2029 uint16_t *wfacename;
2050 U_OUT_DEFAULT_PRECIS,
2051 U_CLIP_DEFAULT_PRECIS,
2053 U_DEFAULT_PITCH | U_FF_DONTCARE,
2057 rec = extcreatefontindirectw_set(&hfont,
eht, (
char *) &lf,
nullptr);
2059 g_error(
"Fatal programming error in PrintEmf::text at extcreatefontindirectw_set");
2063 rec = selectobject_set(hfont,
eht);
2065 g_error(
"Fatal programming error in PrintEmf::text at selectobject_set");
2068 auto rgb = style->
fill.getColor();
2074 g_error(
"Fatal programming error in PrintEmf::text at U_EMRSETTEXTCOLOR_set");
2085 p2[
Geom::X] += ky * std::sin(rotb);
2086 p2[
Geom::Y] += ky * std::cos(rotb);
2092 dy = params.
f3 * style->
font_size.computed * std::cos(rotb);
2093 }
else if (fix90n == 2) {
2094 dx = params.
f2 * style->
font_size.computed * std::sin(rotb);
2097 dx = params.
f1 * style->
font_size.computed * std::sin(rotb);
2098 dy = params.
f1 * style->
font_size.computed * std::cos(rotb);
2107 int32_t
const xpos = (int32_t) round(p2[
Geom::X]);
2108 int32_t
const ypos = (int32_t) round(p2[
Geom::Y]);
2123 }, ndx, 2, unicode_text, U_ETO_NONE, U_RCL_DEF, adx);
2127 }, ndx, 2, unicode_text, U_ETO_RTLREADING, U_RCL_DEF, adx);
2131 rec = U_EMREXTTEXTOUTW_set(U_RCL_DEF, U_GM_COMPATIBLE, 1.0, 1.0, (
PU_EMRTEXT)rec2);
2134 g_error(
"Fatal programming error in PrintEmf::text at U_EMREXTTEXTOUTW_set");
2138 rec = selectobject_set(U_DEVICE_DEFAULT_FONT,
eht);
2140 g_error(
"Fatal programming error in PrintEmf::text at selectobject_set");
2144 rec = deleteobject_set(&hfont,
eht);
2146 g_error(
"Fatal programming error in PrintEmf::text at deleteobject_set");
2158 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI
"\">\n"
2159 "<name>Enhanced Metafile Print</name>\n"
2160 "<id>org.inkscape.print.emf</id>\n"
2161 "<param gui-hidden=\"true\" name=\"destination\" type=\"string\"></param>\n"
2162 "<param gui-hidden=\"true\" name=\"textToPath\" type=\"bool\">true</param>\n"
2163 "<param gui-hidden=\"true\" name=\"pageBoundingBox\" type=\"bool\">true</param>\n"
2164 "<param gui-hidden=\"true\" name=\"FixPPTCharPos\" type=\"bool\">false</param>\n"
2165 "<param gui-hidden=\"true\" name=\"FixPPTDashLine\" type=\"bool\">false</param>\n"
2166 "<param gui-hidden=\"true\" name=\"FixPPTGrad2Polys\" type=\"bool\">false</param>\n"
2167 "<param gui-hidden=\"true\" name=\"FixPPTLinGrad\" type=\"bool\">false</param>\n"
2168 "<param gui-hidden=\"true\" name=\"FixPPTPatternAsHatch\" type=\"bool\">false</param>\n"
2169 "<param gui-hidden=\"true\" name=\"FixImageRot\" type=\"bool\">false</param>\n"
2171 "</inkscape-extension>", std::make_unique<PrintEmf>());
Path - a sequence of contiguous curves.
Cairo integration helpers.
3x3 matrix representing an affine transformation.
Coord expansionX() const
Calculates the amount of x-scaling imparted by the Affine.
Coord expansionY() const
Calculates the amount of y-scaling imparted by the Affine.
C height() const
Get the vertical extent of the rectangle.
C width() const
Get the horizontal extent of the rectangle.
Axis-aligned rectangle that can be empty.
Sequence::const_iterator const_iterator
bool empty() const
Check whether the vector contains any paths.
Sequence of contiguous curves, aka spline.
void close(bool closed=true)
Set whether the path is closed.
const_iterator end_open() const
void append(Curve *curve)
Add a new curve to the end of the path.
const_iterator begin() const
void start(Point const &p)
Function defined as discrete pieces.
void concat(const Piecewise< T > &other)
Two-dimensional point that doubles as a vector.
constexpr Point cw() const
Return a point like this point but rotated +90 degrees.
Axis aligned, non-empty rectangle.
Rotation around the origin.
Geom::PathVector merge_PathVector_with_group(Geom::PathVector const &combined_pathvector, SPItem const *item, const Geom::Affine &transform)
unsigned int image(Inkscape::Extension::Print *module, unsigned char *px, unsigned int w, unsigned int h, unsigned int rs, Geom::Affine const &transform, SPStyle const *style) override
Some parts based on win32.cpp by Lauris Kaplinski lauris@kaplinski.com.
int create_brush(SPStyle const *style, PU_COLORREF fcolor) override
unsigned int fill(Inkscape::Extension::Print *module, Geom::PathVector const &pathv, Geom::Affine const &ctm, SPStyle const *style, Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox) override
unsigned int setup(Inkscape::Extension::Print *module) override
unsigned int draw_pathv_to_EMF(Geom::PathVector const &pathv, const Geom::Affine &transform)
Geom::PathVector merge_PathVector_with_shape(Geom::PathVector const &combined_pathvector, SPItem const *item, const Geom::Affine &transform)
Geom::Path pathv_to_rect(Geom::PathVector const &pathv, bool *is_rect, double *angle)
int vector_rect_alignment(double angle, Geom::Point vtest)
void destroy_brush() override
unsigned int text(Inkscape::Extension::Print *module, char const *text, Geom::Point const &p, SPStyle const *style) override
Geom::Path pathv_to_simple_polygon(Geom::PathVector const &pathv, int *vertices)
unsigned int stroke(Inkscape::Extension::Print *module, Geom::PathVector const &pathv, Geom::Affine const &ctm, SPStyle const *style, Geom::OptRect const &pbox, Geom::OptRect const &dbox, Geom::OptRect const &bbox) override
void destroy_pen() override
unsigned int print_pathv(Geom::PathVector const &pathv, const Geom::Affine &transform)
bool print_simple_shape(Geom::PathVector const &pathv, const Geom::Affine &transform)
int create_pen(SPStyle const *style, const Geom::Affine &transform) override
static void smuggle_adxkyrtl_out(const char *string, uint32_t **adx, double *ky, int *rtl, int *ndx, float scale)
void do_clip_if_present(SPStyle const *style)
U_TRIVERTEX make_trivertex(Geom::Point Pt, U_COLORREF uc)
unsigned int begin(Inkscape::Extension::Print *module, SPDocument *doc) override
Geom::Point get_pathrect_corner(Geom::Path pathRect, double angle, int corner)
unsigned int finish(Inkscape::Extension::Print *module) override
Class to hold image data for raster images.
guchar const * pixels() const
PixelFormat pixelFormat() const
static double convert(double from_dist, Unit const *from, Unit const *to)
Convert distances.
Interface for refcounted XML nodes.
virtual char const * attribute(char const *key) const =0
Get the string representation of a node's attribute.
Typed SVG document implementation.
SPRoot * getRoot()
Returns our SPRoot.
Geom::OptRect preferredBounds() const
Geom::Scale getDocumentScale(bool computed=true) const
Returns document scale as defined by width/height (in pixels) and viewBox (real world to user-units).
Inkscape::XML::Node * getReprNamedView()
SPGradientVector vector
Linear and Radial Gradients.
void ensureVector()
Forces vector to be built, if not present (i.e.
Base class for visual SVG elements.
Geom::OptRect desktopVisualBounds() const
Get item's visual bbox in desktop coordinate system.
SPClipPath * getClipObject() const
T< SPAttr::TEXT_DECORATION_LINE, SPITextDecorationLine > text_decoration_line
CSS 3 2.1, 2.2, 2.3.
T< SPAttr::FONT_WEIGHT, SPIEnum< SPCSSFontWeight > > font_weight
Weight of the font.
T< SPAttr::FILL, SPIPaint > fill
fill
T< SPAttr::STROKE_DASHARRAY, SPIDashArray > stroke_dasharray
stroke-dasharray
T< SPAttr::STROKE, SPIPaint > stroke
stroke
SPObject * object
Object we are attached to.
T< SPAttr::FONT_FAMILY, SPIString > font_family
Font family.
T< SPAttr::STROKE_WIDTH, SPILength > stroke_width
stroke-width
T< SPAttr::FILL_RULE, SPIEnum< SPWindRule > > fill_rule
fill-rule: 0 nonzero, 1 evenodd
T< SPAttr::FILL_OPACITY, SPIScale24 > fill_opacity
fill-opacity
T< SPAttr::FONT_STYLE, SPIEnum< SPCSSFontStyle > > font_style
Font style.
T< SPAttr::STROKE_LINEJOIN, SPIEnum< SPStrokeJoinType > > stroke_linejoin
stroke-linejoin
T< SPAttr::STROKE_MITERLIMIT, SPIFloat > stroke_miterlimit
stroke-miterlimit
T< SPAttr::STROKE_LINECAP, SPIEnum< SPStrokeCapType > > stroke_linecap
stroke-linecap
T< SPAttr::FONT_SIZE, SPIFontSize > font_size
Size of the font.
vector< vpsc::Rectangle * > rs
Enhanced Metafile printing - implementation.
Specific curve type functions for Inkscape, not provided by lib2geom.
bool is_straight_curve(Geom::BezierCurve const &c)
Geom::PathVector pathv_to_linear_and_cubic_beziers(Geom::PathVector const &pathv)
Specific geometry functions for Inkscape, not provided my lib2geom.
Mini static library that contains the version of Inkscape.
Angle distance(Angle const &a, Angle const &b)
PathVector path_from_piecewise(Piecewise< D2< SBasis > > const &B, double tol, bool only_cubicbeziers=false)
Make a path from a d2 sbasis.
Point unit_vector(Point const &a)
bool are_near(Affine const &a1, Affine const &a2, Coord eps=EPSILON)
A set of useful color modifying functions which do not fit as generic methods on the color class itse...
static bool FixPPTDashLine
static bool FixPPTCharPos
static bool FixPPTGrad2Polys
static bool FixPPTPatternAsHatch
U_COLORREF toColorRef(std::optional< Colors::Color > color)
static bool FixPPTLinGrad
void build_from_mem(gchar const *buffer, std::unique_ptr< Implementation::Implementation > in_imp)
Create a module from a buffer holding an XML description.
Helper class to stream background task notifications as a series of messages.
char const * version_string
full version string
Geom::PathVector sp_pathvector_boolop(Geom::PathVector const &pathva, Geom::PathVector const &pathvb, BooleanOp bop, FillRule fra, FillRule frb)
Perform a boolean operation on two pathvectors.
TODO: insert short description here.
PathVector - a sequence of subpaths.
double ang(Point n1, Point n2)
Conversion between SBasis and Bezier basis polynomials.
SVG <image> implementation.
Some things pertinent to all visible shapes: SPItem, SPItemView, SPItemCtx.
TODO: insert short description here.
SVG <pattern> implementation.
TODO: insert short description here.
SPRoot: SVG <svg> implementation.
The various create functions need a place to put their handles, these are stored in the table below.
Storage for keeping track of properties of the growing EMF file as records are added.
std::vector< SPGradientStop > stops
For U_EMR_* OffBmi* fields.
uint8_t Red
Red color (0-255)
uint8_t Reserved
Not used.
uint8_t Blue
Blue color (0-255)
uint8_t Green
Green color (0-255)
For U_EMR[POLY]EXTTEXTOUT[A|W] emrtext field.
For U_EMREXTCREATEPEN lopn field.
For U_EMRGRADIENTFILL GradObj field.
uint32_t UpperLeft
Index of UL corner in an array of U_TRIVERTEX objects.
uint32_t LowerRight
Index of LR corner in an array of U_TRIVERTEX objects.
For U_EMRCREATEBRUSHINDIRECT lb field.
For U_LOGFONT elfLogFont field.
int32_t left
left coordinate
int32_t right
right coordinate
int32_t bottom
bottom coordinate
int32_t top
top coordinate
For GRADIENT_[TRIANGLE|U_RECT].
uint16_t Green
Green component.
uint16_t Red
Red component.
uint16_t Alpha
Alpha Transparency.
uint16_t Blue
Bule component.
SPStyle enums: named public enums that correspond to SVG property values.
@ SP_CSS_FONT_STYLE_ITALIC
SPStyle - a style object for SPItem objects.
parse SVG path specifications
Enhanced Metafile Input/Output.
void UnicodeToNon(uint16_t *text, int *ecount, int *edest)
char * FontName(int code)
void dot(Cairo::RefPtr< Cairo::Context > &cr, double x, double y)
struct U_PAIR U_POINTL
WMF manual 2.2.2.15.
uint32_t U_STYLEENTRY
StyleEntry For U_EXTLOGPEN.
uint32_t U_NUM_STYLEENTRY
Number of U_STYLEENTRY.
size_t wchar16len(const uint16_t *src)
uint16_t * U_Utf8ToUtf16le(const char *src, size_t max, size_t *len)
int U_Utf16leEdit(uint16_t *src, uint16_t find, uint16_t replace)