|
7 | 7 |
|
8 | 8 | #include "litehtml_c.h" |
9 | 9 | #include <litehtml.h> |
| 10 | +#include <litehtml/render_item.h> |
10 | 11 | #include <cstring> |
11 | 12 | #include <string> |
12 | 13 |
|
@@ -1123,4 +1124,154 @@ int lh_document_media_changed(lh_document_t* doc) |
1123 | 1124 | return internal->doc->media_changed() ? 1 : 0; |
1124 | 1125 | } |
1125 | 1126 |
|
| 1127 | +/* -------------------------------------------------------------------------- |
| 1128 | + * Element introspection |
| 1129 | + * -------------------------------------------------------------------------- */ |
| 1130 | + |
| 1131 | +lh_element_t* lh_element_parent(lh_element_t* el) |
| 1132 | +{ |
| 1133 | + if (!el) return nullptr; |
| 1134 | + auto* elem = reinterpret_cast<litehtml::element*>(el); |
| 1135 | + auto parent = elem->parent(); |
| 1136 | + if (!parent) return nullptr; |
| 1137 | + return reinterpret_cast<lh_element_t*>(parent.get()); |
| 1138 | +} |
| 1139 | + |
| 1140 | +int lh_element_children_count(lh_element_t* el) |
| 1141 | +{ |
| 1142 | + if (!el) return 0; |
| 1143 | + auto* elem = reinterpret_cast<litehtml::element*>(el); |
| 1144 | + return static_cast<int>(elem->children().size()); |
| 1145 | +} |
| 1146 | + |
| 1147 | +lh_element_t* lh_element_child_at(lh_element_t* el, int index) |
| 1148 | +{ |
| 1149 | + if (!el) return nullptr; |
| 1150 | + auto* elem = reinterpret_cast<litehtml::element*>(el); |
| 1151 | + const auto& kids = elem->children(); |
| 1152 | + if (index < 0 || index >= static_cast<int>(kids.size())) |
| 1153 | + return nullptr; |
| 1154 | + auto it = kids.begin(); |
| 1155 | + std::advance(it, index); |
| 1156 | + return reinterpret_cast<lh_element_t*>(it->get()); |
| 1157 | +} |
| 1158 | + |
| 1159 | +int lh_element_is_text(lh_element_t* el) |
| 1160 | +{ |
| 1161 | + if (!el) return 0; |
| 1162 | + auto* elem = reinterpret_cast<litehtml::element*>(el); |
| 1163 | + return elem->is_text() ? 1 : 0; |
| 1164 | +} |
| 1165 | + |
| 1166 | +uintptr_t lh_element_get_font(lh_element_t* el) |
| 1167 | +{ |
| 1168 | + if (!el) return 0; |
| 1169 | + auto* elem = reinterpret_cast<litehtml::element*>(el); |
| 1170 | + return elem->css().get_font(); |
| 1171 | +} |
| 1172 | + |
| 1173 | +float lh_element_get_font_size(lh_element_t* el) |
| 1174 | +{ |
| 1175 | + if (!el) return 0.0f; |
| 1176 | + auto* elem = reinterpret_cast<litehtml::element*>(el); |
| 1177 | + return elem->css().get_font_size(); |
| 1178 | +} |
| 1179 | + |
| 1180 | +void lh_element_get_placement(lh_element_t* el, lh_position_t* pos) |
| 1181 | +{ |
| 1182 | + if (!el || !pos) return; |
| 1183 | + auto* elem = reinterpret_cast<litehtml::element*>(el); |
| 1184 | + litehtml::position p = elem->get_placement(); |
| 1185 | + *pos = to_c(p); |
| 1186 | +} |
| 1187 | + |
| 1188 | +void lh_element_get_text(lh_element_t* el, |
| 1189 | + void (*cb)(void* ctx, const char* text), |
| 1190 | + void* ctx) |
| 1191 | +{ |
| 1192 | + if (!el || !cb) return; |
| 1193 | + auto* elem = reinterpret_cast<litehtml::element*>(el); |
| 1194 | + litehtml::string text; |
| 1195 | + elem->get_text(text); |
| 1196 | + cb(ctx, text.c_str()); |
| 1197 | +} |
| 1198 | + |
| 1199 | +lh_element_t* lh_document_get_element_by_point(lh_document_t* doc, |
| 1200 | + float x, float y, |
| 1201 | + float client_x, float client_y) |
| 1202 | +{ |
| 1203 | + if (!doc) return nullptr; |
| 1204 | + auto* internal = reinterpret_cast<lh_document_internal*>(doc); |
| 1205 | + auto root_render = internal->doc->root_render(); |
| 1206 | + if (!root_render) return nullptr; |
| 1207 | + auto el = root_render->get_element_by_point(x, y, client_x, client_y, |
| 1208 | + [](const std::shared_ptr<litehtml::render_item>&) { return true; }); |
| 1209 | + if (!el) return nullptr; |
| 1210 | + return reinterpret_cast<lh_element_t*>(el.get()); |
| 1211 | +} |
| 1212 | + |
| 1213 | +/* -------------------------------------------------------------------------- |
| 1214 | + * Inline box helpers |
| 1215 | + * |
| 1216 | + * get_inline_boxes() returns local-coordinate boxes from the render item. |
| 1217 | + * We compute the same parent-chain offset that get_placement() uses, then |
| 1218 | + * apply it to each box so callers get absolute document coordinates. |
| 1219 | + * -------------------------------------------------------------------------- */ |
| 1220 | + |
| 1221 | +/* Compute parent-chain offset: placement.{x,y} - m_pos.{x,y} */ |
| 1222 | +static void compute_ri_offset(const std::shared_ptr<litehtml::render_item>& ri, |
| 1223 | + float& ox, float& oy) |
| 1224 | +{ |
| 1225 | + litehtml::position placement = ri->get_placement(); |
| 1226 | + litehtml::position pos = ri->pos(); |
| 1227 | + ox = placement.x - pos.x; |
| 1228 | + oy = placement.y - pos.y; |
| 1229 | +} |
| 1230 | + |
| 1231 | +int lh_element_get_inline_boxes_count(lh_element_t* el) |
| 1232 | +{ |
| 1233 | + if (!el) return 0; |
| 1234 | + auto* elem = reinterpret_cast<litehtml::element*>(el); |
| 1235 | + auto ri = elem->get_render_item(); |
| 1236 | + if (!ri) return 0; |
| 1237 | + litehtml::position::vector boxes; |
| 1238 | + ri->get_inline_boxes(boxes); |
| 1239 | + return static_cast<int>(boxes.size()); |
| 1240 | +} |
| 1241 | + |
| 1242 | +void lh_element_get_inline_box_at(lh_element_t* el, int index, lh_position_t* pos) |
| 1243 | +{ |
| 1244 | + if (!el || !pos) return; |
| 1245 | + auto* elem = reinterpret_cast<litehtml::element*>(el); |
| 1246 | + auto ri = elem->get_render_item(); |
| 1247 | + if (!ri) return; |
| 1248 | + |
| 1249 | + litehtml::position::vector boxes; |
| 1250 | + ri->get_inline_boxes(boxes); |
| 1251 | + if (index < 0 || index >= static_cast<int>(boxes.size())) |
| 1252 | + return; |
| 1253 | + |
| 1254 | + float ox, oy; |
| 1255 | + compute_ri_offset(ri, ox, oy); |
| 1256 | + |
| 1257 | + litehtml::position box = boxes[index]; |
| 1258 | + box.x += ox; |
| 1259 | + box.y += oy; |
| 1260 | + *pos = to_c(box); |
| 1261 | +} |
| 1262 | + |
| 1263 | +int lh_element_get_text_align(lh_element_t* el) |
| 1264 | +{ |
| 1265 | + if (!el) return 0; |
| 1266 | + auto* elem = reinterpret_cast<litehtml::element*>(el); |
| 1267 | + return static_cast<int>(elem->css().get_text_align()); |
| 1268 | +} |
| 1269 | + |
| 1270 | +float lh_element_get_line_height(lh_element_t* el) |
| 1271 | +{ |
| 1272 | + if (!el) return 0.0f; |
| 1273 | + auto* elem = reinterpret_cast<litehtml::element*>(el); |
| 1274 | + return elem->css().line_height().computed_value; |
| 1275 | +} |
| 1276 | + |
1126 | 1277 | } /* extern "C" */ |
0 commit comments