Skip to content

Instantly share code, notes, and snippets.

@v6ak
Created November 8, 2012 11:31
Show Gist options
  • Select an option

  • Save v6ak/4038281 to your computer and use it in GitHub Desktop.

Select an option

Save v6ak/4038281 to your computer and use it in GitHub Desktop.
Skript na přidání ořezových značek v SVG. Hodí se v původním obrázku přesáhnout okraje. Omlouvám se za magické konstanty, někde jsem to kdyi vyčetl a nejsem tiskař (a bohužel jsem si to nepoznamenal).
import xml._
trait Rect[+T]{
def x: T
def y: T
def fun(name: String) = name+"("+x+","+y+")"
}
final case class OrientedRect[+T](vertical: T, horizontal: T) extends Rect[T]{
def width = horizontal
def height = vertical
def x = horizontal
def y = vertical
def map[U](f: (T=>U)) = OrientedRect.fromXY(x = f(x), y = f(y))
def unorient(d: Direction): UnorientedRect[T] = UnorientedRect[T](x=d.primary(this), y=d.secondary(this))
def combine[U >: T, V](that: OrientedRect[U], pf: (T, U) =>V) = OrientedRect(
vertical = pf(this.vertical, that.vertical),
horizontal = pf(this.horizontal, that.horizontal)
)
}
object OrientedRect{
def fromXY[T](x: T, y: T): OrientedRect[T] = apply(vertical = y, horizontal = x)
def fromSizes[T](width: T, height: T): OrientedRect[T] = apply(vertical = height, horizontal = width)
def fromAttrs[F, T](f: (String) => T, xName: String, yName: String) = fromXY(f(xName), f(yName))
def fromSizeAttrs[F, T](f: (String) => T) = fromAttrs(f, "width", "height")
def fromXYAttrs[F, T](f: (String) => T) = fromAttrs(f, "x", "y")
}
final case class UnorientedRect[+T](x: T, y: T) extends Rect[T]{
def toOriented(d: Direction): OrientedRect[T] = d.createOrientedRect(this)
}
implicit def toUnorientedRectIntOnlyOperations(left: UnorientedRect[Int]) = new AnyRef{
def onlyPrimary = UnorientedRect(x=left.x, y=0)
def onlySecondary = UnorientedRect(x=0, y=left.y)
}
implicit def toUnorientedRectStringOnlyOperations(left: UnorientedRect[String]) = new AnyRef{
def onlyPrimary = UnorientedRect(x=left.x, y="0")
def onlySecondary = UnorientedRect(x="0", y=left.y)
}
implicit def toOrientedRectIntOnlyOperations(that: OrientedRect[Int]) = new AnyRef{
def onlyPrimary(direction: Direction): OrientedRect[Int] = that.unorient(direction).onlyPrimary.toOriented(direction)
def onlySecondary(direction: Direction) = that.unorient(direction).onlySecondary.toOriented(direction)
}
implicit def toOrientedRectStringOnlyOperations(that: OrientedRect[String]) = new AnyRef{
def onlyPrimary(direction: Direction) = that.unorient(direction).onlyPrimary.toOriented(direction)
def onlySecondary(direction: Direction) = that.unorient(direction).onlySecondary.toOriented(direction)
}
sealed abstract class Direction{
def primary[T](r: OrientedRect[T]): T
def secondary[T](r: OrientedRect[T]): T
def createOrientedRect[T](r: UnorientedRect[T]): OrientedRect[T] // x=primary
def rotate: Direction
}
object Vertical extends Direction{
override def primary[T](r: OrientedRect[T]) = r.vertical
override def secondary[T](r: OrientedRect[T]) = r.horizontal
override def createOrientedRect[T](r: UnorientedRect[T]) = OrientedRect(vertical = r.x, horizontal = r.y)
override def rotate = Horizontal
}
object Horizontal extends Direction{
override def primary[T](r: OrientedRect[T]) = r.horizontal
override def secondary[T](r: OrientedRect[T]) = r.vertical
override def createOrientedRect[T](r: UnorientedRect[T]) = OrientedRect(horizontal = r.x, vertical = r.y)
override def rotate = Vertical
}
implicit def toOrientedRectIntOperations(left: OrientedRect[Int]) = new AnyRef{
def +(right: OrientedRect[Int]): OrientedRect[Int] = left.combine(right, (a: Int, b: Int) => a+b)
def *(right: Int) = left.map(_*right)
}
implicit def toOrientedRectDoubleOperations(left: OrientedRect[Double]) = new AnyRef{
def +(right: OrientedRect[Double]): OrientedRect[Double] = left.combine(right, (a: Double, b: Double) => a+b)
def *(right: Double) = left.map(_*right)
def *(right: OrientedRect[Double]): OrientedRect[Double] = left.combine(right, (a: Double, b: Double) => a*b)
}
val CropmarkerSize = UnorientedRect(50, 3)
val CropmarkerMovement = UnorientedRect(50, 0)
val MarginInternal = OrientedRect(350, 700)
val Space = OrientedRect(240, 240)
val Array(source) = args
val img = XML.load(source)
val orig = OrientedRect.fromSizeAttrs(img.attributes(_).toString)
val dpi = OrientedRect.fromXYAttrs(d => (img \ ("@{http://www.inkscape.org/namespaces/inkscape}export-"+d+"dpi")).toString.toDouble)// ="24.190001"
def calcScale(dpi: Double) = dpi/25.4/10
val color = "black" //"#000000"
val scale = dpi.map(calcScale)
val margin = MarginInternal.map(_.toDouble) * scale
def cm(direction: Direction, moveBefore: OrientedRect[Any], moveAfter: OrientedRect[Any]) = {
val cmr = CropmarkerSize.toOriented(direction)
val cmm = orig.onlyPrimary(direction) //val cmm = CropmarkerMovement.toOriented(direction)
<rect
style={"fill:"+color}
width={cmr.width.toString}
height={cmr.height.toString}
x="0"
y="0"
transform={List(moveBefore fun "translate", scale fun "scale", moveAfter fun "translate") mkString " "} />
}
def genCM(direction: Direction, offset: OrientedRect[String]) = {
val cmr = CropmarkerSize.toOriented(direction)
val cmm = orig.onlyPrimary(direction)//
val sp = Space.onlyPrimary(direction)
<g transform={offset.onlyPrimary(direction.rotate) fun "translate"}>
{cm(direction, OrientedRect(0, 0), (cmr+sp) * -1)}
{cm(direction, cmm, sp)}
</g>
}
val generatedCM = <g>{
for(
cmType <- List(Vertical, Horizontal);
offset <- List(OrientedRect("0", "0"), orig)
) yield genCM(cmType, offset)
}</g>
val newSize = orig.map(_.toDouble) + margin*2
val newImg = img match {
case Elem(prefix, label, attrs, metadata, scope, children @ _*) =>
Elem(
prefix, label, attrs, metadata, scope,
<g transform={margin fun "translate"}>{children}{generatedCM}</g>
) %
new UnprefixedAttribute("width", newSize.width toString, Null) %
new UnprefixedAttribute("height", newSize.height toString, Null)
}
println(newImg)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment