diff --git a/100_core/src/gplx/Math_.java b/100_core/src/gplx/Math_.java
index b970760d0..c7e8c9708 100644
--- a/100_core/src/gplx/Math_.java
+++ b/100_core/src/gplx/Math_.java
@@ -22,6 +22,7 @@ public class Math_ {
public static double E = java.lang.Math.E;
public static int Ceil_as_int(double v) {return (int)Ceil(v);}
public static double Ceil(double v) {return java.lang.Math.ceil(v);}
+ public static int Floor_as_int(double v) {return (int)Floor(v);}
public static double Floor(double v) {return java.lang.Math.floor(v);}
public static double Round(double v, int places) {
return java.math.BigDecimal.valueOf(v).setScale(places, java.math.BigDecimal.ROUND_HALF_UP).doubleValue();
diff --git a/400_xowa/src/gplx/xowa/mws/Xomw_linker.java b/400_xowa/src/gplx/xowa/mws/Xomw_linker.java
index cb76c01a3..53e9998a7 100644
--- a/400_xowa/src/gplx/xowa/mws/Xomw_linker.java
+++ b/400_xowa/src/gplx/xowa/mws/Xomw_linker.java
@@ -37,8 +37,6 @@ public class Xomw_linker {
private final byte[][] split_trail_rv = new byte[2][];
private Btrie_slim_mgr split_trail_trie;
private final Xomw_atr_mgr tmp_attribs = new Xomw_atr_mgr();
- private final Xomw_MediaTransformOutputParams params_list = new Xomw_MediaTransformOutputParams();
- private final Xomw_MediaTransformOutputParams mto_params = new Xomw_MediaTransformOutputParams();
private static final byte[] Atr__class = Bry_.new_a7("class"), Atr__rel = Bry_.new_a7("rel"), Atr__href = Bry_.new_a7("href"), Rel__nofollow = Bry_.new_a7("nofollow");
public static final byte[]
@@ -65,7 +63,7 @@ public class Xomw_linker {
// @param Parser $parser
// @param Title $title Title Object of the file (not the currently viewed page)
// @param File $file File Object, or false if it doesn't exist
- // @param array frame_params Associative array of parameters external to the media handler.
+ // @param array frameParams Associative array of parameters external to the media handler.
// Boolean parameters are indicated by presence or absence, the value is arbitrary and
// will often be false.
// thumbnail If present, downscale and frame
@@ -93,7 +91,7 @@ public class Xomw_linker {
// @param int|null width_option Used by the parser to remember the user preference thumbnailsize
// @since 1.20
// @return String HTML for an image, with links, wrappers, etc.
- public void makeImageLink(Bry_bfr bfr, Xomw_parser parser, Xoa_ttl title, Xomw_File file, Xomw_params_frame frame_params, Xomw_params_handler handler_params, Object time, byte[] query, Object widthOption) {
+ public void makeImageLink(Bry_bfr bfr, Xomw_parser_ctx pctx, Xomw_parser parser, Xoa_ttl title, Xomw_File file, Xomw_params_frame frameParams, Xomw_params_handler handler_params, Object time, byte[] query, Object widthOption) {
// XO.MW.HOOK:ImageBeforeProduceHTML
if (file != null && !file.allowInlineDisplay()) {
@@ -103,25 +101,25 @@ public class Xomw_linker {
// Clean up parameters
int page = handler_params.page;
- if (frame_params.align == null) {
- frame_params.align = Bry_.Empty;
+ if (frameParams.align == null) {
+ frameParams.align = Bry_.Empty;
}
- if (frame_params.alt == null) {
- frame_params.alt = Bry_.Empty;
+ if (frameParams.alt == null) {
+ frameParams.alt = Bry_.Empty;
}
- if (frame_params.title == null) {
- frame_params.title = Bry_.Empty;
+ if (frameParams.title == null) {
+ frameParams.title = Bry_.Empty;
}
- if (frame_params.cls == null) {
- frame_params.cls = Bry_.Empty;
+ if (frameParams.cls == null) {
+ frameParams.cls = Bry_.Empty;
}
byte[] prefix = Bry_.Empty; byte[] postfix = Bry_.Empty;
- if (Bry_.Eq(Align__frame__center, frame_params.align)) {
+ if (Bry_.Eq(Align__frame__center, frameParams.align)) {
prefix = Prefix__center;
postfix = Gfh_tag_.Div_rhs;
- frame_params.align = Align__frame__none;
+ frameParams.align = Align__frame__none;
}
if (file != null && handler_params.width == Php_utl_.Null_int) {
if (handler_params.height != Php_utl_.Null_int && file.isVectorized()) {
@@ -134,10 +132,10 @@ public class Xomw_linker {
handler_params.width = file.getWidth(page);
}
- if ( frame_params.thumbnail != null
- || frame_params.manual_thumb != null
- || frame_params.framed != null
- || frame_params.frameless != null
+ if ( frameParams.thumbnail != null
+ || frameParams.manual_thumb != null
+ || frameParams.framed != null
+ || frameParams.frameless != null
|| handler_params.width == Php_utl_.Null_int
) {
// global $wgThumbLimits, $wgThumbUpright;
@@ -147,16 +145,16 @@ public class Xomw_linker {
// }
// Reduce width for upright images when parameter 'upright' is used
- if (frame_params.upright == 0) {
-// frame_params.upright = $wgThumbUpright;
+ if (frameParams.upright == 0) {
+// frameParams.upright = $wgThumbUpright;
}
// For caching health: If width scaled down due to upright
// parameter, round to full __0 pixel to avoid the creation of a
// lot of odd thumbs.
int pref_width = parser.Env().User__default__thumbsize;
-// pref_width = isset(frame_params['upright']) ?
-// round($wgThumbLimits[width_option] * frame_params['upright'], -1) :
+// pref_width = isset(frameParams['upright']) ?
+// round($wgThumbLimits[width_option] * frameParams['upright'], -1) :
// $wgThumbLimits[width_option];
// Use width which is smaller: real image width or user preference width
@@ -168,24 +166,24 @@ public class Xomw_linker {
}
}
- if (frame_params.thumbnail != null || frame_params.manual_thumb != null
- || frame_params.framed != null
+ if (frameParams.thumbnail != null || frameParams.manual_thumb != null
+ || frameParams.framed != null
) {
// Create a thumbnail. Alignment depends on the writing direction of
// the page content language (right-aligned for LTR languages,
// left-aligned for RTL languages)
// If a thumbnail width has not been provided, it is set
// to the default user option as specified in Language*.php
- if (frame_params.align == Bry_.Empty) {
- frame_params.align = parser.Env().Lang__align_end;
+ if (frameParams.align == Bry_.Empty) {
+ frameParams.align = parser.Env().Lang__align_end;
}
bfr.Add(prefix);
- this.Make_thumb_link2(bfr, title, file, frame_params, handler_params, time, query);
+ this.Make_thumb_link2(bfr, pctx, title, file, frameParams, handler_params, time, query);
bfr.Add(postfix);
return;
}
- if (file != null && frame_params.frameless != null) {
+ if (file != null && frameParams.frameless != null) {
int src_width = file.getWidth(page);
// For "frameless" option: do not present an image bigger than the
// source (for bitmap-style images). This is the same behavior as the
@@ -206,26 +204,26 @@ public class Xomw_linker {
byte[] s = null;
if (thumb == null) {
-// $s = self::makeBrokenImageLinkObj($title, frame_params['title'], '', '', '', $time == true);
+// $s = self::makeBrokenImageLinkObj($title, frameParams['title'], '', '', '', $time == true);
s = Bry_.Empty;
}
else {
// self::processResponsiveImages($file, $thumb, handler_params);
- params_list.Clear();
- params_list.alt = frame_params.alt;
- params_list.title = frame_params.title;
- params_list.valign = frame_params.valign;
- params_list.img_cls = frame_params.cls;
- if (frame_params.border != null) {
- params_list.img_cls = Xomw_params_frame.Cls_add(params_list.img_cls, Img_class__thumbborder);
+ Xomw_params_mto prms = pctx.Linker__makeImageLink__prms.Clear();
+ prms.alt = frameParams.alt;
+ prms.title = frameParams.title;
+ prms.valign = frameParams.valign;
+ prms.img_cls = frameParams.cls;
+ if (frameParams.border != null) {
+ prms.img_cls = Xomw_params_frame.Cls_add(prms.img_cls, Img_class__thumbborder);
}
-// $params = self::getImageLinkMTOParams(frame_params, $query, $parser) + $params;
+ getImageLinkMTOParams(prms, frameParams, query, parser);
- thumb.toHtml(tmp, tmp_2, params_list);
+ thumb.toHtml(tmp, tmp_2, prms);
s = tmp.To_bry_and_clear();
}
- if (frame_params.align != Bry_.Empty) {
- tmp.Add_str_a7("
");
tmp.Add_str_a7("
");
@@ -246,24 +244,24 @@ public class Xomw_linker {
// @param Parser|null $parser
// @return array
// XO.MW:SYNC:1.29; DATE:2017-02-03
- public void Get_image_link_mto_params(Xomw_MediaTransformOutputParams mto_params, Xomw_params_frame frame_params, byte[] query, Xomw_parser parser) {
- if (Php_utl_.isset(frame_params.link_url) && frame_params.link_url != Bry_.Empty) {
- mto_params.custom_url_link = frame_params.link_url;
- if (Php_utl_.isset(frame_params.link_target)) {
- mto_params.custom_target_link = frame_params.link_target;
+ private static void getImageLinkMTOParams(Xomw_params_mto mto_params, Xomw_params_frame frameParams, byte[] query, Xomw_parser parser) {
+ if (Php_utl_.isset(frameParams.link_url) && frameParams.link_url != Bry_.Empty) {
+ mto_params.custom_url_link = frameParams.link_url;
+ if (Php_utl_.isset(frameParams.link_target)) {
+ mto_params.custom_target_link = frameParams.link_target;
}
if (parser != null) {
-// extLinkAttrs = parser->getExternalLinkAttribs(frame_params['link-url']);
+// extLinkAttrs = parser->getExternalLinkAttribs(frameParams['link-url']);
// foreach (extLinkAttrs as name => val) {
// // Currently could include 'rel' and 'target'
// mto_params['parser-extlink-' . name] = val;
// }
}
}
- else if (Php_utl_.isset(frame_params.link_title) && frame_params.link_title != Bry_.Empty) {
-// mto_params.custom_title_link = Title::newFromLinkTarget(Normalize_speecial_page(frame_params.link_title));
+ else if (Php_utl_.isset(frameParams.link_title) && frameParams.link_title != Bry_.Empty) {
+// mto_params.custom_title_link = Title::newFromLinkTarget(Normalize_speecial_page(frameParams.link_title));
}
- else if (!Php_utl_.Empty(frame_params.no_link)) {
+ else if (!Php_utl_.Empty(frameParams.no_link)) {
// No link
}
else {
@@ -272,26 +270,26 @@ public class Xomw_linker {
}
}
- public void Make_thumb_link2(Bry_bfr bfr, Xoa_ttl title, Xomw_File file, Xomw_params_frame frame_params, Xomw_params_handler handler_params, Object time, byte[] query) {
+ public void Make_thumb_link2(Bry_bfr bfr, Xomw_parser_ctx pctx, Xoa_ttl title, Xomw_File file, Xomw_params_frame frameParams, Xomw_params_handler handler_params, Object time, byte[] query) {
boolean exists = true; // = $file && $file->exists();
int page = handler_params.page;
- if (frame_params.align == null) {
- frame_params.align = Align__frame__right;
+ if (frameParams.align == null) {
+ frameParams.align = Align__frame__right;
}
- if (frame_params.alt == null) {
- frame_params.alt = Bry_.Empty;
+ if (frameParams.alt == null) {
+ frameParams.alt = Bry_.Empty;
}
- if (frame_params.title == null) {
- frame_params.title = Bry_.Empty;
+ if (frameParams.title == null) {
+ frameParams.title = Bry_.Empty;
}
- if (frame_params.caption == null) {
- frame_params.caption = Bry_.Empty;
+ if (frameParams.caption == null) {
+ frameParams.caption = Bry_.Empty;
}
if (handler_params.width == Php_utl_.Null_int) {
// Reduce width for upright images when parameter 'upright' is used
- handler_params.width = frame_params.upright != Php_utl_.Null_int ? 130 : 180;
+ handler_params.width = frameParams.upright != Php_utl_.Null_int ? 130 : 180;
}
boolean no_scale = false;
boolean manual_thumb = false;
@@ -302,9 +300,9 @@ public class Xomw_linker {
outer_width = handler_params.width + 2;
}
else {
- if (frame_params.manual_thumb != null) {
+ if (frameParams.manual_thumb != null) {
// Use manually specified thumbnail
-// $manual_title = Title::makeTitleSafe(NS_FILE, frame_params['manual_thumb']);
+// $manual_title = Title::makeTitleSafe(NS_FILE, frameParams['manual_thumb']);
// if ($manual_title) {
// $manual_img = wfFindFile($manual_title);
// if ($manual_img) {
@@ -315,7 +313,7 @@ public class Xomw_linker {
// }
// }
}
- else if (frame_params.framed != null) {
+ else if (frameParams.framed != null) {
// Use image dimensions, don't scale
// thumb = $file->getUnscaledThumb(handler_params);
thumb = new Xomw_ThumbnailImage(file, file.getUrl(), file.getUrl(), file.getWidth(), file.getHeight());
@@ -349,19 +347,19 @@ public class Xomw_linker {
// $url = wfAppendQuery($url, [ 'page' => $page ]);
// }
if (manual_thumb
- && frame_params.link_title != null
- && frame_params.link_url != null
- && frame_params.no_link != null) {
- frame_params.link_url = url;
+ && frameParams.link_title != null
+ && frameParams.link_url != null
+ && frameParams.no_link != null) {
+ frameParams.link_url = url;
}
int rv_bgn = bfr.Len();
- bfr.Add_str_a7("");
byte[] zoom_icon = Bry_.Empty;
if (!exists) {
-// $s .= self::makeBrokenImageLinkObj($title, frame_params.title, '', '', '', $time == true);
+// $s .= self::makeBrokenImageLinkObj($title, frameParams.title, '', '', '', $time == true);
zoom_icon = Bry_.Empty;
}
else if (thumb == null) {
@@ -373,13 +371,14 @@ public class Xomw_linker {
if (!no_scale && !manual_thumb) {
// self::processResponsiveImages($file, thumb, handler_params);
}
- mto_params.Clear();
- mto_params.alt = frame_params.alt;
- mto_params.title = frame_params.title;
- mto_params.img_cls = Xomw_params_frame.Cls_add(frame_params.cls, Img_class__thumbimage);
- Get_image_link_mto_params(mto_params, frame_params, query, null);
- thumb.toHtml(bfr, tmp, mto_params);
- if (frame_params.framed != null) {
+ Xomw_params_mto prms = pctx.Linker__makeImageLink__prms.Clear();
+ prms.alt = frameParams.alt;
+ prms.title = frameParams.title;
+ prms.img_cls = Xomw_params_frame.Cls_add(frameParams.cls, Img_class__thumbimage);
+
+ getImageLinkMTOParams(prms, frameParams, query, null);
+ thumb.toHtml(bfr, tmp, prms);
+ if (frameParams.framed != null) {
zoom_icon = Bry_.Empty;
}
else {
@@ -395,7 +394,7 @@ public class Xomw_linker {
zoom_icon = tmp.To_bry_and_clear();
}
}
- bfr.Add_str_a7("
").Add(zoom_icon).Add(frame_params.caption).Add_str_a7("
");
+ bfr.Add_str_a7(" ").Add(zoom_icon).Add(frameParams.caption).Add_str_a7("
");
Bry_.Replace_all_direct(bfr.Bfr(), Byte_ascii.Nl, Byte_ascii.Space, rv_bgn, bfr.Len()); // str_replace("\n", ' ', $s);
}
@@ -647,18 +646,18 @@ public class Xomw_linker {
// public static function makeThumbLinkObj(Title $title, $file, $label = '', $alt,
// $align = 'right', $params = [], $framed = false, $manual_thumb = ""
// ) {
-// frame_params = [
+// frameParams = [
// 'alt' => $alt,
// 'caption' => $label,
// 'align' => $align
// ];
// if ($framed) {
-// frame_params['framed'] = true;
+// frameParams['framed'] = true;
// }
// if ($manual_thumb) {
-// frame_params['manual_thumb'] = $manual_thumb;
+// frameParams['manual_thumb'] = $manual_thumb;
// }
-// return self::makeThumbLink2($title, $file, frame_params, $params);
+// return self::makeThumbLink2($title, $file, frameParams, $params);
// }
// // Make a "broken" link to an image
diff --git a/400_xowa/src/gplx/xowa/mws/filerepo/file/Xomw_File.java b/400_xowa/src/gplx/xowa/mws/filerepo/file/Xomw_File.java
index 401677c19..a39a0e954 100644
--- a/400_xowa/src/gplx/xowa/mws/filerepo/file/Xomw_File.java
+++ b/400_xowa/src/gplx/xowa/mws/filerepo/file/Xomw_File.java
@@ -1984,25 +1984,26 @@ public class Xomw_File {
//
// return this.pageCount;
// }
-//
-// /**
-// * Calculate the height of a thumbnail using the source and destination width
-// *
-// * @param int srcWidth
-// * @param int srcHeight
-// * @param int dstWidth
-// *
-// * @return int
-// */
-// static function scaleHeight(srcWidth, srcHeight, dstWidth) {
-// // Exact integer multiply followed by division
-// if (srcWidth == 0) {
-// return 0;
-// } else {
-// return (int)round(srcHeight * dstWidth / srcWidth);
-// }
-// }
-//
+
+ /**
+ * Calculate the height of a thumbnail us_ing the source and destination width
+ *
+ * @param int srcWidth
+ * @param int srcHeight
+ * @param int dstWidth
+ *
+ * @return int
+ */
+ public static int scaleHeight(int srcWidth, int srcHeight, int dstWidth) {
+ // Exact integer multiply followed by division
+ if (srcWidth == 0) {
+ return 0;
+ }
+ else {
+ return (int)Math_.Round(srcHeight * dstWidth / srcWidth, 0);
+ }
+ }
+
// /**
// * Get an image size array like that returned by getImageSize(), or false if it
// * can't be determined. Loads the image size directly from the file ignoring caches.
diff --git a/400_xowa/src/gplx/xowa/mws/filerepo/file/Xomw_file_finder__mock.java b/400_xowa/src/gplx/xowa/mws/filerepo/file/Xomw_file_finder__mock.java
index ca9442b89..ac3de092a 100644
--- a/400_xowa/src/gplx/xowa/mws/filerepo/file/Xomw_file_finder__mock.java
+++ b/400_xowa/src/gplx/xowa/mws/filerepo/file/Xomw_file_finder__mock.java
@@ -21,6 +21,7 @@ public class Xomw_file_finder__mock implements Xomw_file_finder {
private final Xomw_parser_env env;
public Xomw_file_finder__mock(Xomw_parser_env env) {this.env = env;}
private final Hash_adp hash = Hash_adp_.New();
+ public void Clear() {hash.Clear();}
public Xomw_File Find_file(Xoa_ttl ttl) {
return (Xomw_File)hash.Get_by(ttl.Page_db_as_str());
}
diff --git a/400_xowa/src/gplx/xowa/mws/media/Xomw_ImageHandler.java b/400_xowa/src/gplx/xowa/mws/media/Xomw_ImageHandler.java
index 8083c1abd..02b3655f1 100644
--- a/400_xowa/src/gplx/xowa/mws/media/Xomw_ImageHandler.java
+++ b/400_xowa/src/gplx/xowa/mws/media/Xomw_ImageHandler.java
@@ -19,9 +19,6 @@ package gplx.xowa.mws.media; import gplx.*; import gplx.xowa.*; import gplx.xowa
import gplx.xowa.mws.filerepo.file.*; import gplx.xowa.mws.parsers.lnkis.*;
import gplx.xowa.mws.utls.*;
/* XO.TODO:
- * parseParamString
- * fitBoxWidth
- * scaleHeight
* validateThumbParams
*/
// MEMORY:only one instance per wiki
@@ -73,13 +70,20 @@ public abstract class Xomw_ImageHandler extends Xomw_MediaHandler { private fina
return Bry_.Add(Int_.To_bry(width), Xomw_lnki_wkr.Bry__px);
}
-// public function parseParamString(str) {
-// m = false;
-// if (preg_match('/^(\d+)px/', str, m)) {
-// return [ 'width' => m[1] ];
-// } else {
-// return false;
+// public Xomw_param_map parseParamString(byte[] src) {
+// int len = src.length;
+// // XO.MW.REGEX: if (preg_match('/^(\d+)px/', str, m)) {
+// if ( len > 0 // at least one char
+// && Byte_ascii.Is_num(src[0])) // 1st char is numeric
+// {
+// pos = Bry_find_.Find_fwd_while_num(src, 1, len); // skip numeric
+// if (Bry_.Match(src, pos, len, Xomw_lnki_wkr.Bry__px)) { // matches "px"
+// Xomw_params_handler rv = new Xomw_params_handler();
+// rv.width = Bry_.To_int_or(src, 0, pos, Php_utl_.Null_int);
+// return rv;
+// }
// }
+// return null;
// }
// function getScriptParams(paramsVar) {
@@ -92,7 +96,7 @@ public abstract class Xomw_ImageHandler extends Xomw_MediaHandler { private fina
* @return boolean
*/
@Override public boolean normaliseParams(Xomw_File image, Xomw_params_handler handlerParams) {
-// mimeType = image.getMimeType();
+ byte[] mimeType = image.getMimeType();
if (!Php_utl_.isset(handlerParams.width)) {
return false;
@@ -119,7 +123,7 @@ public abstract class Xomw_ImageHandler extends Xomw_MediaHandler { private fina
// Height & width were both set
if (handlerParams.width * srcHeight > handlerParams.height * srcWidth) {
// Height is the relative smaller dimension, so scale width accordingly
-// handlerParams.width = self::fitBoxWidth(srcWidth, srcHeight, handlerParams.height);
+ handlerParams.width = fitBoxWidth(srcWidth, srcHeight, handlerParams.height);
if (handlerParams.width == 0) {
// Very small image, so we need to rely on client side scaling :(
@@ -141,57 +145,60 @@ public abstract class Xomw_ImageHandler extends Xomw_MediaHandler { private fina
// Because thumbs are only referred to by width, the height always needs
// to be scaled by the width to keep the thumbnail sizes consistent,
// even if it was set inside the if block above
-// handlerParams.physicalHeight = File::scaleHeight(srcWidth, srcHeight,
-// handlerParams.physicalWidth);
+ handlerParams.physicalHeight = Xomw_File.scaleHeight(srcWidth, srcHeight,
+ handlerParams.physicalWidth);
// Set the height if it was not validated in the if block higher up
if (!Php_utl_.isset(handlerParams.height) || handlerParams.height == -1) {
handlerParams.height = handlerParams.physicalHeight;
}
-// if (!this.validateThumbParams(handlerParams.physicalWidth,
-// handlerParams.physicalHeight, srcWidth, srcHeight, mimeType)
-// ) {
-// return false;
-// }
+ if (!this.validateThumbParams(handlerParams, srcWidth, srcHeight, mimeType)
+ ) {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Validate thumbnail parameters and fill in the correct height
+ *
+ * @param int width Specified width (input/output)
+ * @param int height Height (output only)
+ * @param int srcWidth Width of the source image
+ * @param int srcHeight Height of the source image
+ * @param String mimeType Unused
+ * @return boolean False to indicate that an error should be returned to the user.
+ */
+ // XO.MW.NOTE: MW passes w and h by ref, but only changes h; XO will pass handlerParams directly
+ private boolean validateThumbParams(Xomw_params_handler handlerParams, int srcWidth, int srcHeight, byte[] mimeType) {
+ int width = handlerParams.physicalWidth;
+ int height = handlerParams.physicalHeight;
+ // width = intval(width);
+
+ // Sanity check width
+ if (width <= 0) {
+ Gfo_usr_dlg_.Instance.Warn_many("", "", "validateThumbParams: Invalid destination width: width");
+
+ return false;
+ }
+ if (srcWidth <= 0) {
+ Gfo_usr_dlg_.Instance.Warn_many("", "", "validateThumbParams: Invalid source width: srcWidth");
+
+ return false;
+ }
+
+ height = Xomw_File.scaleHeight(srcWidth, srcHeight, width);
+ if (height == 0) {
+ // Force height to be at least 1 pixel
+ height = 1;
+ }
+ handlerParams.height = height;
return true;
}
-// /**
-// * Validate thumbnail parameters and fill in the correct height
-// *
-// * @param int width Specified width (input/output)
-// * @param int height Height (output only)
-// * @param int srcWidth Width of the source image
-// * @param int srcHeight Height of the source image
-// * @param String mimeType Unused
-// * @return boolean False to indicate that an error should be returned to the user.
-// */
-// function validateThumbParams(&width, &height, srcWidth, srcHeight, mimeType) {
-// width = intval(width);
-//
-// # Sanity check width
-// if (width <= 0) {
-// wfDebug(__METHOD__ . ": Invalid destination width: width\n");
-//
-// return false;
-// }
-// if (srcWidth <= 0) {
-// wfDebug(__METHOD__ . ": Invalid source width: srcWidth\n");
-//
-// return false;
-// }
-//
-// height = File::scaleHeight(srcWidth, srcHeight, width);
-// if (height == 0) {
-// # Force height to be at least 1 pixel
-// height = 1;
-// }
-//
-// return true;
-// }
-//
// /**
// * @param File image
// * @param String script
diff --git a/400_xowa/src/gplx/xowa/mws/media/Xomw_ImageHandler__tst.java b/400_xowa/src/gplx/xowa/mws/media/Xomw_ImageHandler__tst.java
new file mode 100644
index 000000000..43e681509
--- /dev/null
+++ b/400_xowa/src/gplx/xowa/mws/media/Xomw_ImageHandler__tst.java
@@ -0,0 +1,63 @@
+/*
+XOWA: the XOWA Offline Wiki Application
+Copyright (C) 2012 gnosygnu@gmail.com
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU Affero General Public License as
+published by the Free Software Foundation, either version 3 of the
+License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU Affero General Public License for more details.
+
+You should have received a copy of the GNU Affero General Public License
+along with this program. If not, see .
+*/
+package gplx.xowa.mws.media; import gplx.*; import gplx.xowa.*; import gplx.xowa.mws.*;
+import org.junit.*; import gplx.core.tests.*;
+import gplx.xowa.mws.utls.*;
+import gplx.xowa.mws.parsers.*; import gplx.xowa.mws.parsers.lnkis.*;
+import gplx.xowa.mws.filerepo.*; import gplx.xowa.mws.filerepo.file.*;
+public class Xomw_ImageHandler__tst {
+ private final Xomw_ImageHandler__fxt fxt = new Xomw_ImageHandler__fxt();
+ @Before public void init() {
+ fxt.Init__file("A.png", 400, 200);
+ }
+ @Test public void normaliseParams() {
+ // widthOnly; "Because thumbs are only referred to by width, the height always needs"
+ fxt.Test__normaliseParams(fxt.Make__handlerParams(200), fxt.Make__handlerParams(200, 100, 200, 100));
+ }
+}
+class Xomw_ImageHandler__fxt {
+ private final Xomw_ImageHandler handler;
+ private final Xomw_FileRepo repo = new Xomw_FileRepo(Bry_.new_a7("/orig"), Bry_.new_a7("/thumb"));
+ private final Xomw_parser_env env = new Xomw_parser_env();
+ private Xomw_File file;
+ public Xomw_ImageHandler__fxt() {
+ handler = new Xomw_TransformationalImageHandler(Bry_.new_a7("test_handler"));
+ }
+ public Xomw_params_handler Make__handlerParams(int w) {return Make__handlerParams(w, Php_utl_.Null_int, Php_utl_.Null_int, Php_utl_.Null_int);}
+ public Xomw_params_handler Make__handlerParams(int w, int h, int phys_w, int phys_h) {
+ Xomw_params_handler rv = new Xomw_params_handler();
+ rv.width = w;
+ rv.height = h;
+ rv.physicalWidth = phys_w;
+ rv.physicalHeight = phys_h;
+ return rv;
+ }
+ public void Init__file(String title, int w, int h) {
+ this.file = new Xomw_LocalFile(env, Bry_.new_u8(title), repo, w, h, Xomw_MediaHandlerFactory.Mime__image__png);
+ }
+ public void Test__normaliseParams(Xomw_params_handler prms, Xomw_params_handler expd) {
+ // exec
+ handler.normaliseParams(file, prms);
+
+ // test
+ Gftest.Eq__int(expd.width, prms.width);
+ Gftest.Eq__int(expd.height, prms.height);
+ Gftest.Eq__int(expd.physicalWidth, prms.physicalWidth);
+ Gftest.Eq__int(expd.physicalHeight, prms.physicalHeight);
+ }
+}
diff --git a/400_xowa/src/gplx/xowa/mws/media/Xomw_MediaHandler.java b/400_xowa/src/gplx/xowa/mws/media/Xomw_MediaHandler.java
index 09dc8b319..75bd2eccd 100644
--- a/400_xowa/src/gplx/xowa/mws/media/Xomw_MediaHandler.java
+++ b/400_xowa/src/gplx/xowa/mws/media/Xomw_MediaHandler.java
@@ -616,25 +616,25 @@ public abstract class Xomw_MediaHandler {
// return wfMessage('file-info')->sizeParams($file->getSize())
// ->paramsVar('' . $file->getMimeType() . '')->parse();
// }
-//
-// /**
-// * Calculate the largest thumbnail width for a given original file size
-// * such that the thumbnail's height is at most $maxHeight.
-// * @param int $boxWidth Width of the thumbnail box.
-// * @param int $boxHeight Height of the thumbnail box.
-// * @param int $maxHeight Maximum height expected for the thumbnail.
-// * @return int
-// */
-// public static function fitBoxWidth($boxWidth, $boxHeight, $maxHeight) {
-// $idealWidth = $boxWidth * $maxHeight / $boxHeight;
-// $roundedUp = ceil($idealWidth);
-// if (round($roundedUp * $boxHeight / $boxWidth) > $maxHeight) {
-// return floor($idealWidth);
-// } else {
-// return $roundedUp;
-// }
-// }
-//
+
+ /**
+ * Calculate the largest thumbnail width for a given original file size
+ * such that the thumbnail's height is at most $maxHeight.
+ * @param int $boxWidth Width of the thumbnail box.
+ * @param int $boxHeight Height of the thumbnail box.
+ * @param int $maxHeight Maximum height expected for the thumbnail.
+ * @return int
+ */
+ public static int fitBoxWidth(int boxWidth, int boxHeight, int maxHeight) {
+ double idealWidth = boxWidth * maxHeight / boxHeight;
+ int roundedUp = Math_.Ceil_as_int(idealWidth);
+ if (Math_.Round(roundedUp * boxHeight / boxWidth, 0) > maxHeight) {
+ return Math_.Floor_as_int(idealWidth);
+ } else {
+ return roundedUp;
+ }
+ }
+
// /**
// * Shown in file history box on image description page.
// *
diff --git a/400_xowa/src/gplx/xowa/mws/media/Xomw_MediaTransformOutput.java b/400_xowa/src/gplx/xowa/mws/media/Xomw_MediaTransformOutput.java
index ea03b5840..f0c67323a 100644
--- a/400_xowa/src/gplx/xowa/mws/media/Xomw_MediaTransformOutput.java
+++ b/400_xowa/src/gplx/xowa/mws/media/Xomw_MediaTransformOutput.java
@@ -18,6 +18,7 @@ along with this program. If not, see .
package gplx.xowa.mws.media; import gplx.*; import gplx.xowa.*; import gplx.xowa.mws.*;
import gplx.langs.htmls.*;
import gplx.xowa.mws.utls.*;
+import gplx.xowa.mws.parsers.lnkis.*;
import gplx.xowa.mws.filerepo.file.*;
public abstract class Xomw_MediaTransformOutput {
public Xomw_MediaTransformOutput(Xomw_File file, byte[] url, byte[] path, int width, int height) {
@@ -131,7 +132,7 @@ public abstract class Xomw_MediaTransformOutput {
*
* @return String
*/
- public abstract void toHtml(Bry_bfr bfr, Bry_bfr tmp, Xomw_MediaTransformOutputParams options);
+ public abstract void toHtml(Bry_bfr bfr, Bry_bfr tmp, Xomw_params_mto options);
// /**
// * This will be overridden to return true in error classes
diff --git a/400_xowa/src/gplx/xowa/mws/media/Xomw_ThumbnailImage.java b/400_xowa/src/gplx/xowa/mws/media/Xomw_ThumbnailImage.java
index af030b721..0cf4630d3 100644
--- a/400_xowa/src/gplx/xowa/mws/media/Xomw_ThumbnailImage.java
+++ b/400_xowa/src/gplx/xowa/mws/media/Xomw_ThumbnailImage.java
@@ -129,7 +129,7 @@ public class Xomw_ThumbnailImage extends Xomw_MediaTransformOutput { private fin
// For images, desc-link and file-link are implemented as a click-through. For
// sounds and videos, they may be displayed in other ways.
// XO.MW:SYNC:1.29; DATE:2017-02-03
- @Override public void toHtml(Bry_bfr bfr, Bry_bfr tmp, Xomw_MediaTransformOutputParams options) {
+ @Override public void toHtml(Bry_bfr bfr, Bry_bfr tmp, Xomw_params_mto options) {
byte[] alt = options.alt;
// byte[] query = options.desc_query;
diff --git a/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser_ctx.java b/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser_ctx.java
index b77a6ca92..e03df4a59 100644
--- a/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser_ctx.java
+++ b/400_xowa/src/gplx/xowa/mws/parsers/Xomw_parser_ctx.java
@@ -22,6 +22,7 @@ public class Xomw_parser_ctx {
public Xomw_image_params Lnki_wkr__make_image__img_params = new Xomw_image_params();
public byte[][] Lnki_wkr__make_image__match_magic_word = new byte[2][];
public int[] Lnki_wkr__make_image__img_size = new int[2];
+ public Xomw_params_mto Linker__makeImageLink__prms = new Xomw_params_mto();
public void Init_by_page(Xoa_ttl page_title) {
this.page_title = page_title;
diff --git a/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_lnki_wkr.java b/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_lnki_wkr.java
index 2626a02aa..0d7462e0b 100644
--- a/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_lnki_wkr.java
+++ b/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_lnki_wkr.java
@@ -668,7 +668,7 @@ public class Xomw_lnki_wkr {// THREAD.UNSAFE: caching for repeated calls
// byte[] time = options.time;
Object time = null;
// options = $this->mOptions->getThumbSize()
- linker.makeImageLink(bfr, parser, title, file, frameParams, handlerParams, time, desc_query, null);
+ linker.makeImageLink(bfr, pctx, parser, title, file, frameParams, handlerParams, time, desc_query, null);
// Give the handler a chance to modify the parser Object
// if (handler != null) {
diff --git a/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_lnki_wkr__file__tst.java b/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_lnki_wkr__file__tst.java
index 406cd8d36..a22111e74 100644
--- a/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_lnki_wkr__file__tst.java
+++ b/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_lnki_wkr__file__tst.java
@@ -16,7 +16,9 @@ You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
package gplx.xowa.mws.parsers.lnkis; import gplx.*; import gplx.xowa.*; import gplx.xowa.mws.*; import gplx.xowa.mws.parsers.*;
-import org.junit.*; import gplx.core.tests.*; import gplx.xowa.mws.filerepo.*; import gplx.xowa.mws.filerepo.file.*;
+import org.junit.*; import gplx.core.tests.*;
+import gplx.xowa.mws.filerepo.*; import gplx.xowa.mws.filerepo.file.*;
+import gplx.xowa.mws.media.*;
public class Xomw_lnki_wkr__file__tst {
private final Xomw_lnki_wkr__fxt fxt = new Xomw_lnki_wkr__fxt();
@Before public void init() {
@@ -24,14 +26,28 @@ public class Xomw_lnki_wkr__file__tst {
fxt.Init__file("A.png", 300, 200);
}
@Test public void Plain() {
- fxt.Test__to_html("[[File:A.png]]", "");
+ fxt.Test__to_html("[[File:A.png]]", "");
}
@Test public void Thumb() {
fxt.Test__to_html("[[File:A.png|thumb]]", "");
}
@Test public void Size() {
- fxt.Test__to_html("[[File:A.png|123x456px]]", "");
+ fxt.Test__to_html("[[File:A.png|123x456px]]", "");
}
+ @Test public void fitBoxWidth() {
+ // COMMENT:"Height is the relative smaller dimension, so scale width accordingly"
+ // consider file of 200,100 (2:1)
+ // EX_1: view is 120,40 (3:1)
+ // - dimensions are either (a) 120,80 or (b) 80,40
+ // - use (b) 80,40
+ // EX_2: view is 120,80 (1.5:1)
+ // - dimensions are either (a) 120,60 or (b) 160,80
+ // - use (a) 120,60
+ fxt.Init__file("A.png", 200, 100);
+ fxt.Test__to_html__has("[[File:A.png|120x40px]]", "/80px-A.png");
+ fxt.Test__to_html__has("[[File:A.png|120x80px]]", "/120px-A.png");
+ }
+
@Test public void Test__parseWidthParam() {
int[] img_size = new int[2];
// WxHpx
@@ -76,7 +92,7 @@ class Xomw_lnki_wkr__fxt {
wkr.Clear_state();
}
public void Init__file(String title, int w, int h) {
- file_finder.Add(title, repo, w, h, gplx.xowa.files.Xof_ext_.Mime_type__ary[gplx.xowa.files.Xof_ext_.Id_png]);
+ file_finder.Add(title, repo, w, h, Xomw_MediaHandlerFactory.Mime__image__png);
}
public void Test__parse(String src_str, String expd) {
byte[] src_bry = Bry_.new_u8(src_str);
@@ -85,11 +101,18 @@ class Xomw_lnki_wkr__fxt {
Gftest.Eq__ary__lines(expd, pbfr.Rslt().To_str_and_clear(), src_str);
}
public void Test__to_html(String src_str, String expd) {
+ if (apos) expd = gplx.langs.htmls.Gfh_utl.Replace_apos(expd);
+ Gftest.Eq__ary__lines(expd, Exec__to_html(src_str), src_str);
+ }
+ public void Test__to_html__has(String src_str, String expd) {
+ if (apos) expd = gplx.langs.htmls.Gfh_utl.Replace_apos(expd);
+ Gftest.Eq__bool_y(String_.Has(Exec__to_html(src_str), expd));
+ }
+ private String Exec__to_html(String src_str) {
byte[] src_bry = Bry_.new_u8(src_str);
wkr.Replace_internal_links(pctx, pbfr.Init(src_bry));
wkr.Replace_link_holders(pctx, pbfr);
- if (apos) expd = gplx.langs.htmls.Gfh_utl.Replace_apos(expd);
- Gftest.Eq__ary__lines(expd, pbfr.Rslt().To_str_and_clear(), src_str);
+ return pbfr.Rslt().To_str_and_clear();
}
public void Test__parseWidthParam(int[] img_size, String src_str, int expd_w, int expd_h) {
wkr.parseWidthParam(img_size, Bry_.new_u8(src_str));
diff --git a/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_params_frame.java b/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_params_frame.java
index 78909e8de..bda0f08cb 100644
--- a/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_params_frame.java
+++ b/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_params_frame.java
@@ -34,6 +34,10 @@ public class Xomw_params_frame {
public byte[] link_target = null;
public byte[] no_link = null;
public byte[] border = null;
+ public byte[] custom_url_link = null;
+ public byte[] custom_target_link = null;
+ public boolean desc_link = false;
+ public byte[] desc_query = null;
public double upright = -1;
public void Set(int uid, byte[] val_bry, int val_int) {
switch (uid) {
@@ -41,13 +45,18 @@ public class Xomw_params_frame {
}
}
public Xomw_params_frame Clear() {
+ desc_link = false;
+ upright = -1;
align = valign = caption = frame = framed = frameless
= thumbnail = manual_thumb = alt = title = cls = img_cls
- = link_title = link_url = link_target = no_link = null;
- upright = -1;
+ = link_title = link_url = link_target = no_link
+ = custom_url_link = custom_target_link = desc_query
+ = null;
return this;
}
public void Copy_to(Xomw_params_frame src) {
+ this.desc_link = src.desc_link;
+ this.upright = src.upright;
this.align = src.align;
this.valign = src.valign;
this.caption = src.caption;
@@ -65,7 +74,9 @@ public class Xomw_params_frame {
this.link_target = src.link_target;
this.no_link = src.no_link;
this.border = src.border;
- this.upright = src.upright;
+ this.custom_url_link = src.custom_url_link;
+ this.custom_target_link = src.custom_target_link;
+ this.desc_query = src.desc_query;
}
public static byte[] Cls_add(byte[] lhs, byte[] rhs) {
return Bry_.Len_eq_0(lhs) ? rhs : Bry_.Add(lhs, Byte_ascii.Space_bry, rhs);
diff --git a/400_xowa/src/gplx/xowa/mws/media/Xomw_MediaTransformOutputParams.java b/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_params_mto.java
similarity index 86%
rename from 400_xowa/src/gplx/xowa/mws/media/Xomw_MediaTransformOutputParams.java
rename to 400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_params_mto.java
index f2c275348..5e24e41e4 100644
--- a/400_xowa/src/gplx/xowa/mws/media/Xomw_MediaTransformOutputParams.java
+++ b/400_xowa/src/gplx/xowa/mws/parsers/lnkis/Xomw_params_mto.java
@@ -15,8 +15,8 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see .
*/
-package gplx.xowa.mws.media; import gplx.*; import gplx.xowa.*; import gplx.xowa.mws.*;
-public class Xomw_MediaTransformOutputParams {
+package gplx.xowa.mws.parsers.lnkis; import gplx.*; import gplx.xowa.*; import gplx.xowa.mws.*; import gplx.xowa.mws.parsers.*;
+public class Xomw_params_mto {
public boolean desc_link;
public byte[] alt = null;
public byte[] title = null;
@@ -32,12 +32,13 @@ public class Xomw_MediaTransformOutputParams {
public byte[] custom_target_link = null;
public byte[] parser_extlink_rel = null;
public byte[] parser_extlink_target = null;
- public void Clear() {
+ public Xomw_params_mto Clear() {
desc_link = false;
alt = title = file_link = valign
= desc_query = override_width = override_height = no_dimensions
= custom_url_link = custom_title_link
= parser_extlink_rel = parser_extlink_target
= null;
+ return this;
}
}
diff --git a/400_xowa/src/gplx/xowa/mws/utls/Php_utl_.java b/400_xowa/src/gplx/xowa/mws/utls/Php_utl_.java
index 3aea3c976..b8349a16c 100644
--- a/400_xowa/src/gplx/xowa/mws/utls/Php_utl_.java
+++ b/400_xowa/src/gplx/xowa/mws/utls/Php_utl_.java
@@ -38,4 +38,5 @@ public class Php_utl_ {
return true;
}
public static final int Null_int = Int_.Max_value;
+ public static final byte[] Null_bry = null;
}