View Javadoc
1   /*
2    * #%L
3    * wcm.io
4    * %%
5    * Copyright (C) 2014 wcm.io
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   *
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package io.wcm.handler.media;
21  
22  import java.awt.Rectangle;
23  import java.awt.geom.Rectangle2D;
24  
25  import org.apache.commons.lang3.StringUtils;
26  import org.apache.commons.lang3.builder.EqualsBuilder;
27  import org.apache.commons.lang3.builder.HashCodeBuilder;
28  import org.apache.commons.lang3.builder.ToStringBuilder;
29  import org.apache.commons.lang3.builder.ToStringStyle;
30  import org.apache.commons.lang3.math.NumberUtils;
31  import org.jetbrains.annotations.NotNull;
32  import org.osgi.annotation.versioning.ProviderType;
33  
34  /**
35   * Crop dimension with left, top, width and height as integer.
36   */
37  @ProviderType
38  public final class CropDimension extends Dimension {
39  
40    private final long left;
41    private final long top;
42    private final boolean autoCrop;
43  
44    /**
45     * @param left Left in pixels
46     * @param top Top in pixels
47     * @param width Width in pixels
48     * @param height Height in pixels
49     */
50    public CropDimension(long left, long top, long width, long height) {
51      this(left, top, width, height, false);
52    }
53  
54    /**
55     * @param left Left in pixels
56     * @param top Top in pixels
57     * @param width Width in pixels
58     * @param height Height in pixels
59     * @param autoCrop Mark this dimension as auto-cropped
60     */
61    public CropDimension(long left, long top, long width, long height, boolean autoCrop) {
62      super(width, height);
63      this.left = left;
64      this.top = top;
65      this.autoCrop = autoCrop;
66    }
67  
68    /**
69     * @return Left in pixels
70     */
71    public long getLeft() {
72      return this.left;
73    }
74  
75    /**
76     * @return Top in pixels
77     */
78    public long getTop() {
79      return this.top;
80    }
81  
82    /**
83     * @return Right in pixels
84     */
85    public long getRight() {
86      return getLeft() + getWidth();
87    }
88  
89    /**
90     * @return Bottom in pixels
91     */
92    public long getBottom() {
93      return getTop() + getHeight();
94    }
95  
96    /**
97     * @return true if is dimenions is marked as auto-cropped
98     */
99    public boolean isAutoCrop() {
100     return this.autoCrop;
101   }
102 
103   @Override
104   public int hashCode() {
105     return HashCodeBuilder.reflectionHashCode(this);
106   }
107 
108   @Override
109   public boolean equals(Object obj) {
110     return EqualsBuilder.reflectionEquals(this, obj);
111   }
112 
113   @Override
114   public String toString() {
115     return new ToStringBuilder(this, ToStringStyle.NO_CLASS_NAME_STYLE)
116         .append("left", getLeft())
117         .append("top", getTop())
118         .append("width", getWidth())
119         .append("height", getHeight())
120         .build();
121   }
122 
123   /**
124    * @return Crop string with left,top,right,bottom.
125    */
126   public @NotNull String getCropString() {
127     return getLeft() + "," + getTop() + "," + getRight() + "," + getBottom();
128   }
129 
130   /**
131    * @return Crop string with left,top,width,height.
132    */
133   public @NotNull String getCropStringWidthHeight() {
134     return getLeft() + "," + getTop() + "," + getWidth() + "," + getHeight();
135   }
136 
137   /**
138    * @return Rectangle
139    */
140   public @NotNull Rectangle2D getRectangle() {
141     return new Rectangle((int)getLeft(), (int)getTop(), (int)getWidth(), (int)getHeight());
142   }
143 
144   /**
145    * Get crop dimension from crop string.
146    * Please note: Crop string contains not width/height as 3rd/4th parameter but right, bottom.
147    * @param cropString Cropping string from AEM inplace editor
148    * @return Crop dimension instance
149    * @throws IllegalArgumentException if crop string syntax is invalid
150    */
151   @SuppressWarnings("java:S1192") // ignore duplicated strings
152   public static @NotNull CropDimension fromCropString(@NotNull String cropString) {
153     if (StringUtils.isEmpty(cropString)) {
154       throw new IllegalArgumentException("Invalid crop string: '" + cropString + "'.");
155     }
156 
157     // strip off optional size parameter after "/"
158     String crop = cropString;
159     if (StringUtils.contains(crop, "/")) {
160       crop = StringUtils.substringBefore(crop, "/");
161     }
162 
163     String[] parts = StringUtils.split(crop, ",");
164     if (parts.length != 4) {
165       throw new IllegalArgumentException("Invalid crop string: '" + cropString + "'.");
166     }
167     long x1 = NumberUtils.toLong(parts[0]);
168     long y1 = NumberUtils.toLong(parts[1]);
169     long x2 = NumberUtils.toLong(parts[2]);
170     long y2 = NumberUtils.toLong(parts[3]);
171     long width = x2 - x1;
172     long height = y2 - y1;
173     if (x1 < 0 || y1 < 0 || width <= 0 || height <= 0) {
174       throw new IllegalArgumentException("Invalid crop string: '" + cropString + "'.");
175     }
176     return new CropDimension(x1, y1, width, height);
177   }
178 
179 }