Highlighted

ESTK - draw a graphic

Advocate ,
Nov 03, 2018

Copy link to clipboard

Copied

Dear all,

After the first step (drawing a single line) I now try to draw a polyline. But i have no success:

  • Obviously the defintion for the points is not correct
  • Same is for the defintion of the dash pattern.

I tried to interprete the the FDK reference and the Scripting Guide - but I fail to transfer these definitions to JS data types.

FDK reference

F_PointsT: describes a set of coordinate pairs. It is normally used to describe the vertices of a graphic object, such as a polyline or polygon.

typedef struct {

   UIntT len;     /* Number of coordinate pairs */

   F_PointT *val; /* Vector of coordinate pairs */

} F_PointsT;

Dash: Data type Metrics. Specifies a dash pattern that is repeated for the length of an object's border. The

pattern is stored in a MetricsT structure. The 0th element of the MetricsT.MetricsT_val array stores the length of the first dash; the 1st element

stores the following space; the 2nd element stores the next dash; and so on for an even number of elements.

Metrics: Under this heading some functions to handle metrics are given, but no explanation. I do not find a useful definition.

MetricsT structure: defined as

typedef struct {

   UIntT len;    /* Number of metric values*/

   MetricT *val; /* Array of metric values */

} F_MetricsT;

Scripting Guide

Points: An Array of Point objects with integer indexing and a length property.

Point: is described just as two integer values x and y.

Dash: Same text as in FDK

Metrics: An Array of objects with integer indexing and a length property. ➔ what kind of objects?

This is my script

#target framemaker

var oDoc = app.ActiveDoc, cm = 1857713;

Main(oDoc);

function Main(oDoc) {

var oFrame, oLine1, oPoly1;

  if (!oDoc.ObjectValid()) {

    alert ("A document must be active.");

    return;

  }

 

  oFrame = oDoc.FirstSelectedGraphicInDoc;

  if (!oFrame.ObjectValid()) {

    alert ("An anchored frame must be selected.");

    return;

  }

  oPoly1  = DrawPoly(oDoc, oFrame);

}

function DrawPoly(oDoc, oFrame) {

var j, jLast, k, oPoly = oDoc.NewPolyline(oFrame), oPoints = [4, 1, 6, 2, 8, 1, 10, 2];

  jLast = oPoints.length-1;                       // last index

  for (j = 0; j <= jLast; j++) {                  // convert into internal units

    oPoints = oPoints * cm;

  }

  oPoly.PolyIsBezier = 0;                         // 0: unsmooth; 1: smooth ?

  oPoly.BorderWidth = 0.05*cm;                    // Stroke-width

  oPoly.LocX = oPoints[0];                        // otherwise has

  oPoly.LocY = oPoints[1];                        // precedence over 1st point

  oPoly.Points = oPoints;

  oPoly.Width = oPoints[jLast-1] - oPoints[0];    // object dimensions

  oPoly.Height= oPoints[jLast] - oPoints[1];      // default : 1/4"

  oPoly.Fill  = 15;                               // Pattern: 0: filled, 7: white, 15: clear

  oPoly.Color = 0;                                // black?

  oPoly.Dash  = [cm, 0.5, 0.5, 0.2, 0.2];         // ?

  return oPoly;

}

And this is the output

The red item is what I want to achieve and the black is what the script produces.

polyline1.png

TOPICS
Scripting

Views

874

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more

ESTK - draw a graphic

Advocate ,
Nov 03, 2018

Copy link to clipboard

Copied

Dear all,

After the first step (drawing a single line) I now try to draw a polyline. But i have no success:

  • Obviously the defintion for the points is not correct
  • Same is for the defintion of the dash pattern.

I tried to interprete the the FDK reference and the Scripting Guide - but I fail to transfer these definitions to JS data types.

FDK reference

F_PointsT: describes a set of coordinate pairs. It is normally used to describe the vertices of a graphic object, such as a polyline or polygon.

typedef struct {

   UIntT len;     /* Number of coordinate pairs */

   F_PointT *val; /* Vector of coordinate pairs */

} F_PointsT;

Dash: Data type Metrics. Specifies a dash pattern that is repeated for the length of an object's border. The

pattern is stored in a MetricsT structure. The 0th element of the MetricsT.MetricsT_val array stores the length of the first dash; the 1st element

stores the following space; the 2nd element stores the next dash; and so on for an even number of elements.

Metrics: Under this heading some functions to handle metrics are given, but no explanation. I do not find a useful definition.

MetricsT structure: defined as

typedef struct {

   UIntT len;    /* Number of metric values*/

   MetricT *val; /* Array of metric values */

} F_MetricsT;

Scripting Guide

Points: An Array of Point objects with integer indexing and a length property.

Point: is described just as two integer values x and y.

Dash: Same text as in FDK

Metrics: An Array of objects with integer indexing and a length property. ➔ what kind of objects?

This is my script

#target framemaker

var oDoc = app.ActiveDoc, cm = 1857713;

Main(oDoc);

function Main(oDoc) {

var oFrame, oLine1, oPoly1;

  if (!oDoc.ObjectValid()) {

    alert ("A document must be active.");

    return;

  }

 

  oFrame = oDoc.FirstSelectedGraphicInDoc;

  if (!oFrame.ObjectValid()) {

    alert ("An anchored frame must be selected.");

    return;

  }

  oPoly1  = DrawPoly(oDoc, oFrame);

}

function DrawPoly(oDoc, oFrame) {

var j, jLast, k, oPoly = oDoc.NewPolyline(oFrame), oPoints = [4, 1, 6, 2, 8, 1, 10, 2];

  jLast = oPoints.length-1;                       // last index

  for (j = 0; j <= jLast; j++) {                  // convert into internal units

    oPoints = oPoints * cm;

  }

  oPoly.PolyIsBezier = 0;                         // 0: unsmooth; 1: smooth ?

  oPoly.BorderWidth = 0.05*cm;                    // Stroke-width

  oPoly.LocX = oPoints[0];                        // otherwise has

  oPoly.LocY = oPoints[1];                        // precedence over 1st point

  oPoly.Points = oPoints;

  oPoly.Width = oPoints[jLast-1] - oPoints[0];    // object dimensions

  oPoly.Height= oPoints[jLast] - oPoints[1];      // default : 1/4"

  oPoly.Fill  = 15;                               // Pattern: 0: filled, 7: white, 15: clear

  oPoly.Color = 0;                                // black?

  oPoly.Dash  = [cm, 0.5, 0.5, 0.2, 0.2];         // ?

  return oPoly;

}

And this is the output

The red item is what I want to achieve and the black is what the script produces.

polyline1.png

TOPICS
Scripting

Views

875

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Nov 03, 2018 0
Advocate ,
Nov 05, 2018

Copy link to clipboard

Copied

Even using the function Point (x,y) as described in the Scripting Guide (Function Summary), i have no success. The statement

oPoints = [Point(4*CM, 1*CM), Point(6*CM, 2*CM), Point(8*CM, 1*CM), Point(10*CM, 2*CM)];

yields message Point() is not a function!

var oPoints = [[4*CM, 1*CM], [6*CM, 2*CM], [8*CM, 1*CM], [10*CM, 2*CM]];

is accepted by ESTK, but creates only a line. The UI reports a PolyLine at 0/0 with width=height = 0.635 cm (1/4"). The Stroke width is as set in the script:

polyline2.png

I have also found this:

  • The FDK constants FV_METRIC_xx are not mapped to ESTK.
  • For the typographic unit didot I see a discrepancy between the definition in FM (1/72” * 69977/65536) = 0.376684 and the official definition (1/72 French Royal inch = 0.375972 mm).
  • For Line my simple definition of the points
    var oPoints = [1, 1, 3, 2];
    seems to work - why then not in Polyline?
    line1.png

Where is a description of the required data types in JS terminology?

I'ts also an imposition that for every graphic object (line, arc, ellipse...) simply all properties for any object are listed (most likely by a text inset). IMHO it is at least misleading that a circle can have an arrow head. Well this is obvious, but others are not at all.

Maybe I need to bridle the tail of the ferd and look for a script which lists the set of properties of a selected object...

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 05, 2018 0
Advocate ,
Nov 05, 2018

Copy link to clipboard

Copied

I have now selected my reddish polyline  and run this simple script:

var oDoc = app.ActiveDoc;

var oObject = oDoc.FirstSelectedGraphicInDoc;

$.writeln (oObject.Points[0]);

But I get only this:

[object Point]

And the Data Browser is very closed about the Points:

polyline3.png

So even inspecting existing objects does not reveal the nature of the point structure... GRRRRRRRRRRRRRR

How on earth can i find out how to define the points for the polyline?

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 05, 2018 0
Enthusiast ,
Nov 05, 2018

Copy link to clipboard

Copied

Klaus,

The Data Browser does hide some useful information, but it can be made to reveal its secrets. In your case if you address the object's x or y properties like this you will get the result that may help:

$.writeln (oObject.Points[0].x);

$.writeln (oObject.Points[0].y);

I've not tried to create a polyline yet, but perhaps explicitly referencing x and y will do what you need?

Ian

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 05, 2018 0
Engaged ,
Nov 05, 2018

Copy link to clipboard

Copied

Hi klaus,

creating a list of Points should work like this:

var point1 = new Point(1, 2);

var point2 = new Point(4, 5);

var points = new Points();

points.push(point1)

points.push(point2)

point1.x gives the x-coordinate of a point

point2.y gives the y-coordinate of a point

both values are changeable

Note: you need to provide metrics and not cm or Inches.

To convert cm 2 metric you can use this function

    function convertCm2Metric(widthCm)

    {

        var cm2pt = 28.35;

        return Math.round (widthCm * 65535 * cm2pt)

    }

Hope this helps

Markus

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 05, 2018 0
Advocate ,
Nov 05, 2018

Copy link to clipboard

Copied

@Ian: Thanks - this lets me see what I have at a selected polyline:

var j, oDoc = app.ActiveDoc, oObject, nPoints;

  oObject = oDoc.FirstSelectedGraphicInDoc;

  nPoints = oObject.NumPoints

  for (j = 0; j < nPoints; j++) {

    $.writeln (oObject.Points.x, oObject.Points.y);

  }

With Markus' idea I could create the points (see script output), but the drawn graphic is by no means what I expect (reddish polyline) accoring to the Points.

polyline4.png

#target framemaker

var oDoc = app.ActiveDoc, CM = 1857713;           // Constants.FV_Metric_CM not present in ESTK

Main(oDoc);

function DrawPolyLine(oDoc, oFrame, rVertices, iSmooth) { // === Draw a polygon line ====

var j, jMax, minX, maxX, minY, maxY, oPoly = oDoc.NewPolyline(oFrame);

  jMax = rVertices.length/2;                      // number of points

  minX = minY = Number.MAX_VALUE;

  maxX = maxY = 0;                  // in units

  for (j = 0; j < jMax; j++) {

    oPoint = new Point (rVertices[j*2]* CM, rVertices[j*2+1]* CM);// convert into internal units

$.writeln (oPoint.x + "   " + oPoint.y);

    oPoly.Points.push(oPoint);

    if (rVertices[j*2] < minX) {minX = rVertices[j*2];}

    if (rVertices[j*2+1] < minY) {minY = rVertices[j*2+1];}

    if (rVertices[j*2] > maxX) {maxX = rVertices[j*2];}

    if (rVertices[j*2+1] > maxY) {maxY = rVertices[j*2+1];}

  }

  oPoly.Fill  = 15;                               // equiv Pattern: 0: filled, 7: white, 15: clear

  oPoly.Color = 0;                                // black?

  oPoly.BorderWidth = 0.05*CM;                    // Stroke-width

  oPoly.Dash  = [CM, 0.5, 0.5, 0.2, 0.2];         // not correct yet

  oPoly.LocX = minX * CM;

  oPoly.LocY = minY * CM;

  oPoly.NumPoints = jMax;

  oPoly.PolyIsBezier = iSmooth;

  oPoly.Width = (maxX - minX) * CM;               // object dimensions

  oPoly.Height= (maxY - minY) * CM;               // default : 1/4"

  return oPoly;

} //--- end DrawPolyLine

function Main(oDoc) { // ==========================================================================

var oFrame, oLine1, oPoly1;

var rVertices = [4, 1, 3, 3, 8, 3, 6, 2];         // values in cm

  if (!oDoc.ObjectValid()) {

    alert ("A document must be active.");

    return;

  }

    oFrame = oDoc.FirstSelectedGraphicInDoc;

  if (!oFrame.ObjectValid()) {

    alert ("An anchored frame must be selected.");

    return;

  }

  if (oFrame.constructor.name === "AFrame") {     // If it is an anchored frame, display its anchor type and width.

//    alert ("Anchor type: " + oFrame.AnchorType + " width in CM: " + oFrame.Width/CM);

  }

  oPoly1  = DrawPolyLine(oDoc, oFrame, rVertices, 0);  // unsmoothed line

} //--- end Main

Output:

7430852   1857713

5573139   5573139

14861704   5573139

11146278   3715426

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 05, 2018 0
Engaged ,
Nov 06, 2018

Copy link to clipboard

Copied

Klaus,

drawing polylines is not easy with FrameMaker, as it depends on the order of points and also the settings of polyline properties also.

Fortunately I don't need to do this in my projects 🙂 but I did this in a very long time ago and remember the battle with FrameMaker.

What I would do is to draw a polyline that I expect, and check to points and the order they are set. After that, I would take exactly the same settings, and create the polyline by code with exactly the same values for each point shown in databrowser.

As soon as this works, I would add the same polyline with my own points. And as soon as this fits to, I would change polyline properties.

BTW:

oPoly.Color = 0;                                // black?

Color is an Object, and you have to get it from FM with doc.GetNamedColor("Black").

Please note Standard Color names are localized. You won't get "Black" in a German FM. You Need to call "Schwarz" or "Noir" for French FM.

and for this

oPoly.Fill  = 15

I would use FM constans. Something like Constants.FV_FILL

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 06, 2018 0
Engaged ,
Nov 06, 2018

Copy link to clipboard

Copied

Klaus,

I'm not sure if this would have any effect, but I wouldn't do that:

oPoly.Points.push(oPoint)

I would do

var points = new Points() ;

and assign all Points at once

oPoly.Points = points

In this case FM has nothing to draw while you are calculating the points

and perhaps I would set all oPoly props first and assign Points at last.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 06, 2018 0
Engaged ,
Nov 06, 2018

Copy link to clipboard

Copied

Hi Klaus,

I ran you code and digged a Little bit deeper into that.

As soon as you create a polyline (doc.NewPolyline) FM creates this Default 3 Point line.

Assigning NumPoints and Points later has no effect anymore.

This is why you get this Kind of line. Your Point calculation looks god.

So there must be another way to change the point settings of a polyline.

Perhaps I find some time this evening...

Markus

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 06, 2018 0
Engaged ,
Nov 06, 2018

Copy link to clipboard

Copied

Klaus,

NumPoints and Points are readonly properties in ES (at least when I have a look to ObjectModel-Viewer)

So you can't change that properties directly.

But this also doesn't have any effect…

  var existingPolypointsNum = oPoly.NumPoints;

  for (var i=0; i < existingPolypointsNum; i++)

        oPoly.Points.pop();

  for (var i=0; i < points.length; i++)

        oPoly.Points.push(points);

… but it should…

existing points are not removed and new points are not added.

and as it does not, I assume this feature seems not to be supported by ESTK... while it works with F_ApiSetPoints in FDK

Perhaps SetProps could help, but I don't think so.

For that reason I'm out. Perhaps someone else has an idea.

Markus

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 06, 2018 0
Adobe Community Professional ,
Nov 06, 2018

Copy link to clipboard

Copied

Hi Klaus and Markus,

I haven't posted much but I have been watching this thread and trying a bunch of code and I suspect that Markus is right: there is some kind of a flaw in the ExtendScript implementation. I tried SetProps as well and couldn't get it to work. If I get time, I will clean up my code and post it here and maybe you guys will get some ideas. But of course, if it is broken we might not be able to get it to work anyway.

Rick

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 06, 2018 0
Advocate ,
Nov 06, 2018

Copy link to clipboard

Copied

@Markus:

«NumPoints and Points are readonly properties in ES (at least when I have a look to ObjectModel-Viewer)»

In FDK reference and FM-15 Scripting Guide it is just IntT - no mentioning of Read-Only. In the Object Reference (.chm) by  Jongware (although for FM-12) it is defined readwrite. And in the Object Model Viewer I get:

Polyline.NumPoints ; Data Type: int ; Adobe FrameMaker-2017 Object Model

Where did you see the ReadOnly? Well, this does not prove that it is really writeable...

«What I would do is to draw a polyline that I expect, and check to points and the order they are set.»

The comparison of output and my 'reply' 5 shows that I already did that - because it is natural for math-affined people like me.

Yes, constants are good, if they exist. For the pen pattern only 3 of 15 are definable via constant. The metric values (e.g. FV_METRIC_CM) are not present in ESTK, justin FDK.

@Rick: It seems that PolyLine is broken in ESTK, because there is definitely no possibility to overcome the 3-point limit and the points are not set at all to the user values.

Even after halting the script after these statements Data Browser states: NumPoints = 3 and Points = [object Point],[object Point],[object Point]

var oPoly = oDoc.NewPolyline(oFrame);

  oPoly.Points = [];
  oPoly.Points.length = 0;

I will demomstrate this to Amitoj in Stuttgart.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 06, 2018 0
Engaged ,
Nov 06, 2018

Copy link to clipboard

Copied

Thought I could provide a Workaround by drawing single lines like this

  for (j = 0; j < jMax -1; j++) { 

    var point1 = new Point (rVertices[j*2]* CM, rVertices[j*2+1]* CM);// convert into internal units 

    var point2 = new Point (rVertices[j*2 + 2]* CM, rVertices[j*2+3]* CM);// convert into internal units 

    var line = oDoc.NewLine(oFrame) ;

    line.Points = new Points() ;

    line.Points.push(point1) ;

    line.Points.push(point2);

   

    //$.writeln (oPoint.x + "   " + oPoint.y); 

    //oPoly.Points.push(oPoint); 

    if (rVertices[j*2] < minX) {minX = rVertices[j*2];} 

    if (rVertices[j*2+1] < minY) {minY = rVertices[j*2+1];} 

    if (rVertices[j*2] > maxX) {maxX = rVertices[j*2];} 

    if (rVertices[j*2+1] > maxY) {maxY = rVertices[j*2+1];} 

  }

But there's the same issue. I think it's worth to create a Ticket for Adobe.

Read-Only:

If you press F1 in ESTK you get the Objectmodell-Viewer. If you open FM 2019 model and scroll to Polyline you see the property "Points". Its Icon is gray and in my interpreation this means "read-only".

In FDK this property is not read-only. So this is a gap/bug in ESTK and I think this issue is a general handling of Points-structure.

Hope this helps

Markus

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 06, 2018 0
Advocate ,
Nov 07, 2018

Copy link to clipboard

Copied

Thanks, Markus, for this idea - but you can not create a smoot line this way...

For the sake of reference I have filed two bugs:

https://tracker.adobe.com/#/view/FRMAKER-5568 - ESTK Lack of implementation for various graphic objects

https://tracker.adobe.com/#/view/FRMAKER-5569 - ESTK Function PolyLine does not work at all

Both bug reports have an attached pdf with details.

The tough thing about these: this all is true since FM-10 (and for the Object Styles since FM-11).

I think, our ideas are exhausted now and we can close this discussion - until Adobe react properly.

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 07, 2018 2
Advocate ,
Nov 07, 2018

Copy link to clipboard

Copied

Friends, it's even worse - I must come back to this discussion.

After just one test I was convinced that at least Line works correctly, but new tests are not positive.

Having these points in the calling rouine

first point drawnsecond point
var oPoints = [1, 1, 3, 2]; 1, 1  3, 2
var oPoints = [2, 4, 9, 2]; 2, 4  9, 4.63500013188259
var oPoints = [1.5, 3.5, 9, 2.1];1.5, 3.5  9, 4.13499986273445
var oPoints = [2,2, 3, 10];2, 23, 10
var oPoints = [2,2, 10, 3];2, 2 10, 3
var oPoints = [1,4, 10, 1];1, 410, 4.63500013188259

Only the first point is always correctly placed. The end-point of the line is randomly placed!

The script is this:

function DrawLine (oDoc, oFrame, oPoints) { // === Draw a straight line ===

var j, jLast, k, oLine = oDoc.NewLine(oFrame);

  jLast = oPoints.length-1;                      // last index

  for (j = 0; j <= jLast; j++) {                  // convert into internal units

    oPoints = oPoints * CM;

  }

  oLine.BorderWidth = 0.05*CM;                    // Stroke-width

  oLine.LocX = oPoints[0];                        // otherwise has

  oLine.LocY = oPoints[1];                        // precedence over 1st point

  oLine.Points = oPoints;

  oLine.Width = oPoints[jLast-1] - oPoints[0];    // object dimensions

  oLine.Height= oPoints[jLast] - oPoints[1];      // default : 1/4"

  oLine.Fill  = 0;                                // full

  oLine.Color = 0;                                // black is anyway default

  return oLine;

} //--- end DrawLine

After drawing I use the following script to get the coordinates of the points listed:

// InspectCurrentObject.jsx ==============

// Line or PolyLine object must be selected

#target framemaker

  var j, oDoc = app.ActiveDoc, oObject, nPoints, CM = 1857713;

 

  oObject = oDoc.FirstSelectedGraphicInDoc;

  nPoints = oObject.NumPoints

  for (j = 0; j < nPoints; j++) {

    $.writeln (oObject.Points.x/CM + "\t" + oObject.Points.y/CM);

  }

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 07, 2018 0
Engaged ,
Nov 09, 2018

Copy link to clipboard

Copied

Hi Klaus,

I did also some tests with that and I think handling graphic objects with Points is very buggy in ESTK.

But with FDK it works perfectly, as I did that in the past with very complex und high requirements.But I also remember some strange Things.

So I think you should switch to FDK or save document as MIF and change MIF in an external process.

But BTW: draw a line by Hand and save doc to MIF. Check the coordinates there and see if you will get the same values, which are senseless on a first view. Perhaps on point of FM view this may correct and you have to calculate point values in a different way.

Markus

Likes

Translate

Translate

Report

Report
Community Guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
Reply
Loading...
Nov 09, 2018 0