Tweaking Photoshop transform JavaScript to include scaling variable - extendscript

So after looking around I finally found a something works almost as I need. I plan to use applescript to pass it variables. That said we get to the javascript. I don't know it well and still trying to pick it up.
Can anyone help me add in some code to included scaling the image after the anchor point is defined. The current code also needs the user to confirm the setting. Since I am passing variables I don't need it to do that. I think all i need to do is change "DialogModes.ALL" to "DialogModes.NO"
function transform( x, y) {// anchor position as pixels
var desc = new ActionDescriptor();
var ref = new ActionReference();
ref.putEnumerated( charIDToTypeID('Lyr '), charIDToTypeID('Ordn'), charIDToTypeID('Trgt') );
desc.putReference( charIDToTypeID('null'), ref );
desc.putEnumerated( charIDToTypeID('FTcs'), charIDToTypeID('QCSt'), charIDToTypeID('Qcsi') );
var desc7 = new ActionDescriptor();
desc7.putUnitDouble( charIDToTypeID('Hrzn'), charIDToTypeID('#Rlt'), x );
desc7.putUnitDouble( charIDToTypeID('Vrtc'), charIDToTypeID('#Rlt'), y );
desc.putObject( charIDToTypeID('Pstn'), charIDToTypeID('Pnt '), desc7 );
desc.putUnitDouble( charIDToTypeID('Wdth'), charIDToTypeID('#Prc'), 100 );
desc.putUnitDouble( charIDToTypeID('Hght'), charIDToTypeID('#Prc'), 100 );
desc.putBoolean( charIDToTypeID('Lnkd'), true );
desc.putEnumerated( charIDToTypeID('Intr'), charIDToTypeID('Intp'), charIDToTypeID('Bcbc') );
executeAction( charIDToTypeID('Trnf'), desc, DialogModes.ALL );
};
transform( 584, 330)
I am looking for the function input to look like this in the end.
transform( 584, 330, 50, 50)
That would make 584=X, 330=y Pixel anchor and the 50, 50 would be the percents of the x,y scale.
Any help to polish this would be greatly appreciated. I need to use this as part of a batch action for 10,000 images...

Change the function definition to
function transform(x, y, w, h) {
and change the lines starting with desc.putUnitDouble to the following:
desc.putUnitDouble( charIDToTypeID('Wdth'), charIDToTypeID('#Prc'), w );
desc.putUnitDouble( charIDToTypeID('Hght'), charIDToTypeID('#Prc'), h );

Related

Adding direction handles to geoman markers

I would like to add a direction handle to [some] geoman leaflet markers. There are packages out there already like leaflet-editable-marker that add things like direction/transformation rulers etc to leaflet.
I want [some] outline markers for my polylines to have a direction, and I want to set this direction using those "direction handles" rulers. The rulers should look like an arrow of sorts - a short line and a head.
To set directions, I am thinking about handling dragstart, drag and dragend events.
When users click on such a marker, the editor would show the direction handle; a subsequent click will hide this handle again. Initially, my thinking was to do something like the below:
marker.on('click', (e) => {
const latlng = marker._latlng;
const directionHandleMarker = new L.circleMarker(latlng, {
draggable: true,
radius: 20,
img: {
url: 'icon.png', //image link
size: [40, 40], //image size ( default [40, 40] )
rotate: 10, //image base rotate ( default 0 )
offset: { x: 0, y: 0 }, //image offset ( default { x: 0, y: 0 } )
}
});
...
map.addLayer(directionHandleMarker);
});
The circleMarker is from 'leaflet-canvas-markers' package. It is also pretty trivial to build this arrow marker functionality without a plugin, and there are multiple reference implementations.
However, this won't give me what I want, will it? Since it is a marker, I could not drag it to adjust the angle, or could I? The geoman rotate mixin kind of does it, using cursor position to calculate the angle and using that to place the marker, rather the placing marker based on the cursor position. Would I need to drag the end of an arrow and recompute offset?
Should I add a two-point LineString and fix one point on the marker and use the other end for dragging, or is there a way to make markers [without a polyline] work?

SKIA - Inaccurate value returned by measureText()

I have a problem measuring text using skia measureText() function.
The value returned is inaccurate.
SkPaint *skPaint = new SkPaint();
SkTypeface* myFont = SkTypeface::CreateFromName("Impact", SkTypeface::kNormal);
skPaint->setTypeface(myFont);
skPaint->setAntiAlias(true);
skPaint->setTextAlign(SkPaint::kLeft_Align);
skPaint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
skPaint->setTextSize(SkIntToScalar(120));
skPaint->setColor(0xff000001);
canvas->drawText(text, length, SkIntToScalar(x) , SkIntToScalar(y) , *skPaint);
SkScalar width = skPaint->measureText(text, length);
The width returned by measureText() is 451.
I checked the generated bitmap text via a photo editor app, the actual width is only 438.
Any thoughts on getting the accurate width of text in SKIA?
Thank you!
I believe what you are trying to match will come from "bounds"
SkRect bounds;
SkScalar textWidth = paint.measureText("some", 4, &bounds);
which is a minimum rectangle to fit a given text, whereas textWidth is slightly larger than that.
I faced this issue too. Dont know why exactly it happens, maybe because of kerning differences, but i came to this:
SizeF RenderTextAndroid::GetStringSizeF() {
UpdateFont();
const base::string16& text = GetLayoutText();
std::vector<SkScalar> widths(text.length());
paint_.getTextWidths(text.c_str(), GetStrByteLen(text), &widths[0], NULL);
return SizeF(std::accumulate(widths.begin(), widths.end(), 0),
font_metrics_.fBottom - font_metrics_.fTop);
}
Where UpdateFont just sets new parameters to SkPaint

Appending multiple svg text with d3

I have been stuck on this problem for days.
So I have a dataset of objects of the following form:
dataset = [{metric:"revenue",value:0.03},{metric:"sales", value:0.15},{metric:"churn", value: 0.06},{metric:"logins", value: 0.45}]
The following code would display the 4 metric names in a grid pattern (meshy, meshx are the coordinates points of the grid and meshsize is the size of the grid, so this is just putting the text in the middle of a grid square):
svg.selectAll("text")
.data(dataset)
.enter()
.append("text")
.text(function(d){
return d.metric;
})
.attr("y",function(d,i){
return meshy[i] + meshsize/2;
})
.attr("x", function(d,i){
return meshx[i] + meshsize/2;
})
.attr("font-size",25)
.attr("font-family","serif")
.attr("text-anchor","middle")
.attr("font-weight","bold");
Now I would like to put the value of the metric right underneath the metric name like so:
svg.append("text")
.data(dataset)
.text(function(d){
return (d.value);
})
.attr("y",function(d,i){
return meshy[i] + meshsize/2 + 20;
})
.attr("x", function(d,i){
return meshx[i] + meshsize/2 ;
})
.attr("font-size",25)
.attr("font-family","serif")
.attr("text-anchor","middle")
.attr("font-weight","bold");
But this only returns the value underneath the metric name for the FIRST metric, the other 3 value texts are not even in the DOM. I have tried multiple approaches including replacing .text with .html as described here:https://github.com/mbostock/d3/wiki/Selections#wiki-html with no success. I have also tried appending paragraph elements instead - this works but the p elements are positioned below the svg body in a list with no obvious way to move them into the right position. The code above is the closest I have come to getting what I need, but for some reason only the first value text shows up. However, I am open to any approach in d3 that gets the job done: 4 metric names with the values right underneath them
In your second block of code, you are only appending one text element, hence only one of them is appearing. What you need to do is to append the text similar to your first block, i.e. with the .enter() selection. For this, you have two choices. You can either save and reuse the .enter() selection, or assign different classes to the two kinds of text to be able to distinguish between them.
Option 1:
var texts = svg.selectAll("text")
.data(dataset)
.enter();
texts.append("text")
.text(function(d){
return d.metric;
})
// set position etc.
texts.append("text")
.text(function(d){
return d.value;
})
// set position etc.
Option 2:
svg.selectAll("text.title")
.data(dataset)
.enter()
.append("text")
.attr("class", "title")
.text(function(d){
return d.metric;
})
// set position etc.
svg.selectAll("text.value")
.data(dataset)
.enter()
.append("text")
.attr("class", "value")
.text(function(d){
return d.value;
})
// set position etc.
The first option is obviously shorter, but depending on what else you want to do, the second option may be preferable -- if you want to modify the text afterwards, it will be a lot easier if you can distinguish between the two kinds of text. You can also use the different classes to give different CSS styles.

Converting SVG paths with holes to extruded shapes in three.js

I have a shape that consists of 4 polygons: 2 non-holes and 2 holes. This is only an example. In reality there can be a shape that consists of 50 polygons, of which 20 are non-holes and 30 are holes. In SVG path this like polygon can be represented easily by combining moveto:s and lineto:s. Every sub-polygon (hole or non-hole) in path string starts with moveto-command and ends with z (end) command and non-holes have winding order CW and holes CCW. Very easy and intuitive.
The shape in SVG is represented this way (http://jsbin.com/osoxev/1/edit):
<path d="M305.08,241.97 L306,251.51 L308.18,256.39 L311.72,259.09 L317.31,260.01 L324.71,259.01 L332.45,255.86 L335.57,257.53 L337.6,260.44 L336.94,262.33 L328.27,268.74 L317.89,273.41 L307.94,275.49 L296.26,275.23 L286.64,272.99 L279.78,269.31 L274.14,263.55 L271.65,260.21 L269.2,261.06 L254.83,268.51 L242.11,272.97 L227.59,275.23 L209.91,275.48 L197.47,273.63 L187.91,270.13 L180.48,265.09 L175.32,258.88 L172.2,251.44 L171.1,242.23 L172.24,233.63 L175.49,226.24 L181,219.54 L189.42,213.3 L201.36,207.73 L217.23,203.25 L238.28,200.1 L265.24,198.78 L269.37,198.47 L269.98,182.93 L268.74,171.32 L266.05,163.7 L261.58,157.72 L255.24,153.24 L247.06,150.32 L235.44,149.13 L224.71,150.05 L215.91,153 L210.23,156.86 L207.64,160.85 L207.19,165.28 L209.34,169.86 L212.01,174.15 L212.14,177.99 L209.8,181.78 L204.22,185.79 L197.62,187.68 L188.65,187.43 L182.41,185.39 L178.45,181.77 L176.2,176.9 L176.03,170.64 L178.2,164.13 L183.09,157.69 L191.04,151.36 L202.01,145.82 L216.09,141.57 L232.08,139.24 L250.07,139.18 L266.13,141.23 L279.05,145.06 L289.15,150.3 L295.91,156.19 L300.73,163.41 L303.85,172.47 L305.07,183.78 L305.07,241.97 L305.08,241.97Z
M243.99,64.95 L255.92,66.06 L266.21,69.28 L274.98,74.44 L280.64,80.19 L284.02,86.85 L285.26,94.52 L284.27,102.84 L281.24,109.66 L276.03,115.43 L267.89,120.46 L257.68,123.93 L245.79,125.33 L232.93,124.53 L222.21,121.74 L213.14,117.11 L207.36,111.92 L203.7,105.75 L201.94,98.18 L202.34,90.12 L204.86,83.4 L210.01,76.81 L217.49,71.33 L227.17,67.31 L238.35,65.2 L243.75,64.95 L243.99,64.95Z
M269.99,212.88 L269.48,208.76 L266.59,208.36 L245.76,210.86 L230.95,214.67 L220.9,219.34 L213.82,224.85 L209.69,230.71 L207.92,237.03 L208.4,244.49 L210.86,250.57 L215.2,255.08 L221.69,258.13 L230.57,259.43 L242.52,258.58 L255.27,255.23 L266.07,250.04 L269.34,247.02 L269.99,244.81 L269.99,212.88 L269.99,212.88Z
M243.63,73.34 L235.93,74.4 L230.07,77.36 L225.65,82.21 L223.05,88.57 L222.41,96.92 L223.94,104.53 L227.23,110.22 L231.99,114.29 L238.44,116.65 L246.81,116.94 L253.73,115.1 L258.87,111.5 L262.63,106.12 L264.64,98.93 L264.59,90.25 L262.47,83.41 L258.65,78.43 L253.37,75.08 L246.08,73.43 L243.68,73.34 L243.63,73.34Z"/>
When I try to follow the same logic in three.js, I run into problems. Below is an image of this:
The three.js doesn't seem to understand what moveto means. It should make "pen up" and draw nothing between previous point and point of moveto command. But the "pen doesnt go up" and the shape breaks.
The code portion is this (don't confuse of variable names, they are from other example):
// Create glyph shape (sorry the confusing name):
var starPoints2 = new THREE.Shape();
// Add first polygon
starPoints2.moveTo(307.94,275.49);
starPoints2.lineTo(296.26,275.23);
// .....
starPoints2.lineTo(286.64,272.99);
starPoints2.lineTo(307.94,275.49);
// Add second polygon
starPoints2.moveTo(245.79,125.33);
starPoints2.lineTo(232.93,124.53);
// .....
starPoints2.lineTo(257.68,123.93);
starPoints2.lineTo(245.79,125.33);
// Create path for holes
var smileyEye1Path = new THREE.Path();
// First hole
smileyEye1Path.moveTo(221.69,258.13);
smileyEye1Path.lineTo(215.2,255.08);
// .....
smileyEye1Path.lineTo(230.57,259.43);
smileyEye1Path.lineTo(221.69,258.13);
// Second hole
smileyEye1Path.moveTo(238.44,116.65);
smileyEye1Path.lineTo(231.99,114.29);
// .....
smileyEye1Path.lineTo(246.81,116.94);
smileyEye1Path.lineTo(238.44,116.65);
// Add holes to shape
var starShape = starPoints2;
starShape.holes.push( smileyEye1Path );
// Extrude after that. See the full code here:
// http://jsfiddle.net/pHn2B/33/
function(){}
http://jsfiddle.net/pHn2B/33/
What I'm doing wrong in my code or is there bug in three.js?
You can't have a moveTo in the middle of a shape definition. You have to have two separate shapes. You can do something like this:
var object = new THREE.Object3D();
var shape1 = new THREE.Shape();
var shape2 = new THREE.Shape();
var hole1 = new THREE.Path();
var hole2 = new THREE.Path();
shape1.holes.push( hole1 );
shape2.holes.push( hole2 );
. . .
object.add( mesh1 );
object.add( mesh2 );
scene.add( object );
Fiddle: http://jsfiddle.net/pHn2B/34/
three.js r.58
P.S. Friendly tip: In the future, it would be a good idea to make it easy for people to help you -- edit your variable names and remove unrelated code from your example.

Raphael - Transform after Serialization

I am using Raphael to draw some paths. Each path has an associated rectangle [container] the size and position of the bounding box. I am using the container for dragging both shapes.
In the move callback, I update the both positions so they both move together.
This all works great until I serialize. I am only serializing the path, then creating the container on the fly after deserialization.
Immediately after converting to json and back, things look fine. I can print out the current transform of the path and it looks correct. Doing any transform on the path after this results in the path being reset and moved to 0,0.
Here is a fiddle that shows the problem.
If you move the rect, you can see both objects move together.
If you click 'Save/Load', things look fine, and the path prints the same.
If you now drag, the path gets reset to 0,0. Printing shows the transform has been reset from 0,0.
I am trying to find out how to make the path move as it did before serialization. Is something getting lost in the process? Or is there an internal state that needs to be updated?
Raphael.JSON serialises data stored in the elements. It does not preserve temporary data stored in the paper object so something does indeed get lost in the process when calling R.clear(). For example drag events bound to elements are not preserved.
However the main issue here is with your drag function, notice how dragging the square a second time applies the transformation from the top left of the paper. I suggest using Raphael.FreeTransform (which you already included in the Fiddle) to handle this.
I wrote both Raphael.JSON and Raphael.FreeTransform plugins and have struggled with the same issues. I'm currently working on an application that lets you save save and restore the state of the paper (similar to what you're doing) and it works fine. If you need any help feel free to open an issue on Github.
You need to capture the initial transform offsets of your elements when the drag starts and use those as the basis for your drag-move transforms. Consider the following:
var start_x, start_y;
cont.drag(function(x, y, e)
{
p.transform('t' + ( start_x + x ) + ',' + ( start_y + y ) );
cont.transform('t' + ( start_x + x ) + ',' + ( start_y + y ) );
},
function( x, y )
{
var start_bbox = p.getBBox();
start_x = start_bbox.x;
start_y = start_bbox.y;
console.log("Drag start at %s,%s", start_x, start_y );
} );
I've staged this in a fiddle located here.
Unfortunately, there is still an issue with the path -- it's offset is being incremented by the difference between it's bounding box y value and the y axis (a difference of 12, to be precise) each time drag is used. I'm not sure where that's coming from exactly.

Resources