From 26527a8800585517c562998dbe301307fb4d59b0 Mon Sep 17 00:00:00 2001 From: gnosygnu Date: Wed, 8 Feb 2017 09:44:08 -0500 Subject: [PATCH] Mw_parse: Add fixBoxWidth, scaleByHeight, etc. --- 100_core/src/gplx/Math_.java | 1 + 400_xowa/src/gplx/xowa/mws/Xomw_linker.java | 159 +++++++++--------- .../xowa/mws/filerepo/file/Xomw_File.java | 39 ++--- .../filerepo/file/Xomw_file_finder__mock.java | 1 + .../xowa/mws/media/Xomw_ImageHandler.java | 111 ++++++------ .../mws/media/Xomw_ImageHandler__tst.java | 63 +++++++ .../xowa/mws/media/Xomw_MediaHandler.java | 38 ++--- .../mws/media/Xomw_MediaTransformOutput.java | 3 +- .../xowa/mws/media/Xomw_ThumbnailImage.java | 2 +- .../xowa/mws/parsers/Xomw_parser_ctx.java | 1 + .../xowa/mws/parsers/lnkis/Xomw_lnki_wkr.java | 2 +- .../lnkis/Xomw_lnki_wkr__file__tst.java | 35 +++- .../mws/parsers/lnkis/Xomw_params_frame.java | 17 +- .../lnkis/Xomw_params_mto.java} | 7 +- 400_xowa/src/gplx/xowa/mws/utls/Php_utl_.java | 1 + 15 files changed, 295 insertions(+), 185 deletions(-) create mode 100644 400_xowa/src/gplx/xowa/mws/media/Xomw_ImageHandler__tst.java rename 400_xowa/src/gplx/xowa/mws/{media/Xomw_MediaTransformOutputParams.java => parsers/lnkis/Xomw_params_mto.java} (86%) 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]]", "A.png"); + fxt.Test__to_html("[[File:A.png]]", "A.png"); } @Test public void Thumb() { fxt.Test__to_html("[[File:A.png|thumb]]", "
A.png
"); } @Test public void Size() { - fxt.Test__to_html("[[File:A.png|123x456px]]", "A.png"); + fxt.Test__to_html("[[File:A.png|123x456px]]", "A.png"); } + @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; }